diff options
| author | Nsable-sh <nsable-sh@noreply.git.bitflash.network> | 2026-08-07 11:30:49 -0300 |
|---|---|---|
| committer | Bitflash <admin@bitflash.network> | 2026-08-07 15:05:31 -0300 |
| commit | 5c2e66b70ab3c15603a6e2d7a4ea9e02f3cd0604 (patch) | |
| tree | 360c43d69ce716ad16e1e3868911a3e660c16302 /src | |
| parent | 8c2e375600c0eb9bedb8f85ee4fa860825f23521 (diff) | |
pool: write dashboard status JSON
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.cpp | 1 | ||||
| -rw-r--r-- | src/main.h | 1 | ||||
| -rw-r--r-- | src/main_gui.cpp | 5 | ||||
| -rw-r--r-- | src/rpc.cpp | 83 |
4 files changed, 90 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp index 2610c45..6cb7353 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -104,6 +104,7 @@ bool fMineModeFromCommandLine = false; | |||
| 104 | string strParticipantPool; // participant mode: pool .btf address | 104 | string strParticipantPool; // participant mode: pool .btf address |
| 105 | string strPoolName = "Bitflash Pool"; | 105 | string strPoolName = "Bitflash Pool"; |
| 106 | string strPoolDashboardUrl; | 106 | string strPoolDashboardUrl; |
| 107 | string strPoolStatusFile; | ||
| 107 | double dPoolFeePercent = 0.0; | 108 | double dPoolFeePercent = 0.0; |
| 108 | 109 | ||
| 109 | static std::atomic<uint64> gParticipantSharesSent{0}; | 110 | static std::atomic<uint64> gParticipantSharesSent{0}; |
| @@ -86,6 +86,7 @@ extern bool fMineModeFromCommandLine; | |||
| 86 | extern string strParticipantPool; // participant: pool .btf address | 86 | extern string strParticipantPool; // participant: pool .btf address |
| 87 | extern string strPoolName; // operator: announced pool name | 87 | extern string strPoolName; // operator: announced pool name |
| 88 | extern string strPoolDashboardUrl; // operator: optional dashboard URL | 88 | extern string strPoolDashboardUrl; // operator: optional dashboard URL |
| 89 | extern string strPoolStatusFile; // operator: optional JSON status output path | ||
| 89 | extern double dPoolFeePercent; // operator: announced fee percent | 90 | extern double dPoolFeePercent; // operator: announced fee percent |
| 90 | extern bool fSoloMineTest; // /solomine: mine without requiring a peer (local test) | 91 | extern bool fSoloMineTest; // /solomine: mine without requiring a peer (local test) |
| 91 | // Threads to hash with; 0 = decide from the hardware. Set by /genproclimit. | 92 | // Threads to hash with; 0 = decide from the hardware. Set by /genproclimit. |
diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 875988f..41661b9 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp | |||
| @@ -123,6 +123,7 @@ static void PrintUsage() | |||
| 123 | printf(" /poolname=NAME\n"); | 123 | printf(" /poolname=NAME\n"); |
| 124 | printf(" /poolfee=PCT\n"); | 124 | printf(" /poolfee=PCT\n"); |
| 125 | printf(" /pooldashboard=URL (alias: /pooldash=URL)\n"); | 125 | printf(" /pooldashboard=URL (alias: /pooldash=URL)\n"); |
| 126 | printf(" /poolstatusfile=PATH (write pool status JSON for dashboards)\n"); | ||
| 126 | printf("\n"); | 127 | printf("\n"); |
| 127 | printf(".btf and rendezvous:\n"); | 128 | printf(".btf and rendezvous:\n"); |
| 128 | printf(" /connectbtf=PEER_BTF_ADDRESS\n"); | 129 | printf(" /connectbtf=PEER_BTF_ADDRESS\n"); |
| @@ -239,6 +240,10 @@ static void ParseStartupArguments(int argc, char* argv[]) | |||
| 239 | if (!poolFee.empty()) | 240 | if (!poolFee.empty()) |
| 240 | dPoolFeePercent = atof(poolFee.c_str()); | 241 | dPoolFeePercent = atof(poolFee.c_str()); |
| 241 | 242 | ||
| 243 | string poolStatusFile = argval2(argc, argv, "/poolstatusfile", "-poolstatusfile"); | ||
| 244 | if (!poolStatusFile.empty()) | ||
| 245 | strPoolStatusFile = poolStatusFile; | ||
| 246 | |||
| 242 | string btfConnect = argval2(argc, argv, "/connectbtf", "-connectbtf"); | 247 | string btfConnect = argval2(argc, argv, "/connectbtf", "-connectbtf"); |
| 243 | if (!btfConnect.empty()) | 248 | if (!btfConnect.empty()) |
| 244 | strBtfConnect = btfConnect; | 249 | strBtfConnect = btfConnect; |
diff --git a/src/rpc.cpp b/src/rpc.cpp index 383769a..1aa4f9b 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp | |||
| @@ -623,6 +623,7 @@ static StatsSnapshot gStats; | |||
| 623 | static std::vector<PoolWorkerStatView> gWorkerStats; | 623 | static std::vector<PoolWorkerStatView> gWorkerStats; |
| 624 | static std::vector<PendingPayoutView> gPayoutViews; | 624 | static std::vector<PendingPayoutView> gPayoutViews; |
| 625 | static std::mutex gStatsMutex; | 625 | static std::mutex gStatsMutex; |
| 626 | static int64 gLastPoolStatusWrite = 0; | ||
| 626 | 627 | ||
| 627 | void GetPoolOperatorStats(int& authorizedMiners, int& blocksFound, uint64& roundShares, double& totalHashRate) | 628 | void GetPoolOperatorStats(int& authorizedMiners, int& blocksFound, uint64& roundShares, double& totalHashRate) |
| 628 | { | 629 | { |
| @@ -645,6 +646,82 @@ void GetPendingPayouts(std::vector<PendingPayoutView>& out) | |||
| 645 | out = gPayoutViews; | 646 | out = gPayoutViews; |
| 646 | } | 647 | } |
| 647 | 648 | ||
| 649 | static std::string PoolStatusFilePath() | ||
| 650 | { | ||
| 651 | if (!strPoolStatusFile.empty()) | ||
| 652 | return strPoolStatusFile; | ||
| 653 | return GetAppDir() + "/pool_status.json"; | ||
| 654 | } | ||
| 655 | |||
| 656 | static void WritePoolStatusJsonLocked() | ||
| 657 | { | ||
| 658 | nlohmann::json j; | ||
| 659 | j["schema"] = "bitflash-pool-status-1"; | ||
| 660 | j["network"] = "bitflash"; | ||
| 661 | j["updatedAt"] = GetTime(); | ||
| 662 | |||
| 663 | j["operator"] = { | ||
| 664 | {"name", strPoolName}, | ||
| 665 | {"btfAddress", BtfLocalAddress()}, | ||
| 666 | {"feePercent", dPoolFeePercent}, | ||
| 667 | {"dashboardUrl", strPoolDashboardUrl} | ||
| 668 | }; | ||
| 669 | |||
| 670 | j["node"] = { | ||
| 671 | {"height", nBestHeight}, | ||
| 672 | {"poolRunning", (bool)gPoolRunning}, | ||
| 673 | {"mode", nMineMode} | ||
| 674 | }; | ||
| 675 | |||
| 676 | j["pool"] = { | ||
| 677 | {"authorizedMiners", gStats.authorizedMiners}, | ||
| 678 | {"blocksFoundSession", gStats.blocksFound}, | ||
| 679 | {"roundShares", gStats.roundShares}, | ||
| 680 | {"hashRate", gStats.totalHashRate} | ||
| 681 | }; | ||
| 682 | |||
| 683 | j["workers"] = nlohmann::json::array(); | ||
| 684 | for (const PoolWorkerStatView& row : gWorkerStats) { | ||
| 685 | j["workers"].push_back({ | ||
| 686 | {"address", row.address}, | ||
| 687 | {"worker", row.worker}, | ||
| 688 | {"totalShares", row.totalShares}, | ||
| 689 | {"roundShares", row.roundShares}, | ||
| 690 | {"lastSeen", row.lastSeen}, | ||
| 691 | {"hashRate", row.hashRate} | ||
| 692 | }); | ||
| 693 | } | ||
| 694 | |||
| 695 | j["pendingPayouts"] = nlohmann::json::array(); | ||
| 696 | for (const PendingPayoutView& row : gPayoutViews) { | ||
| 697 | j["pendingPayouts"].push_back({ | ||
| 698 | {"matureAtHeight", row.matureAtHeight}, | ||
| 699 | {"recipients", row.recipients}, | ||
| 700 | {"totalAmountSatoshis", row.totalAmount}, | ||
| 701 | {"totalAmountBtf", FormatMoney(row.totalAmount)} | ||
| 702 | }); | ||
| 703 | } | ||
| 704 | |||
| 705 | std::string path = PoolStatusFilePath(); | ||
| 706 | std::string tmp = path + ".tmp"; | ||
| 707 | FILE* f = fopen(tmp.c_str(), "w"); | ||
| 708 | if (!f) { | ||
| 709 | LogPrint("pool", "[pool] WARNING: could not write status file %s\n", tmp.c_str()); | ||
| 710 | return; | ||
| 711 | } | ||
| 712 | std::string s = j.dump(2); | ||
| 713 | fwrite(s.c_str(), 1, s.size(), f); | ||
| 714 | if (fclose(f) != 0) { | ||
| 715 | LogPrint("pool", "[pool] WARNING: could not close status file %s\n", tmp.c_str()); | ||
| 716 | return; | ||
| 717 | } | ||
| 718 | #ifdef _WIN32 | ||
| 719 | remove(path.c_str()); | ||
| 720 | #endif | ||
| 721 | if (rename(tmp.c_str(), path.c_str()) != 0) | ||
| 722 | LogPrint("pool", "[pool] WARNING: could not replace status file %s\n", path.c_str()); | ||
| 723 | } | ||
| 724 | |||
| 648 | // --------------------------------------------------------------------------- | 725 | // --------------------------------------------------------------------------- |
| 649 | // Miner state -- event loop thread only | 726 | // Miner state -- event loop thread only |
| 650 | // --------------------------------------------------------------------------- | 727 | // --------------------------------------------------------------------------- |
| @@ -1314,6 +1391,12 @@ static void RefreshStats(int blocksFoundThisSession, uint64 roundShareTotal) | |||
| 1314 | if (pv.recipients > 0) | 1391 | if (pv.recipients > 0) |
| 1315 | gPayoutViews.push_back(pv); | 1392 | gPayoutViews.push_back(pv); |
| 1316 | } | 1393 | } |
| 1394 | |||
| 1395 | int64 now = GetTime(); | ||
| 1396 | if (now - gLastPoolStatusWrite >= 10) { | ||
| 1397 | WritePoolStatusJsonLocked(); | ||
| 1398 | gLastPoolStatusWrite = now; | ||
| 1399 | } | ||
| 1317 | } | 1400 | } |
| 1318 | 1401 | ||
| 1319 | // --------------------------------------------------------------------------- | 1402 | // --------------------------------------------------------------------------- |