upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorNsable-sh <nsable-sh@noreply.git.bitflash.network>2026-08-07 11:34:17 -0300
committerBitflash <admin@bitflash.network>2026-08-07 15:06:21 -0300
commit8bf5b8cac5d91165b11d4ce65333b68edcc723b0 (patch)
treede92ea6afbc7762ec3e8f9654544ca56d9448c06 /src/main.cpp
parent5c2e66b70ab3c15603a6e2d7a4ea9e02f3cd0604 (diff)
pool: add local Stratum bridge
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 6cb7353..2be9c54 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -106,6 +106,8 @@ string strPoolName = "Bitflash Pool";
106string strPoolDashboardUrl; 106string strPoolDashboardUrl;
107string strPoolStatusFile; 107string strPoolStatusFile;
108double dPoolFeePercent = 0.0; 108double dPoolFeePercent = 0.0;
109bool fStratumBridge = false;
110int nStratumBridgePort = 3333;
109 111
110static std::atomic<uint64> gParticipantSharesSent{0}; 112static std::atomic<uint64> gParticipantSharesSent{0};
111static std::atomic<uint64> gParticipantSharesAccepted{0}; 113static std::atomic<uint64> gParticipantSharesAccepted{0};
@@ -3873,6 +3875,190 @@ static bool PoolParticipantMiner()
3873 return true; 3875 return true;
3874} 3876}
3875 3877
3878// ---------------------------------------------------------------------------
3879// Local Stratum bridge -- lets external miners speak plain Stratum to
3880// 127.0.0.1 while Bitflash opens the .btf tunnel to the selected pool.
3881// ---------------------------------------------------------------------------
3882
3883struct StratumBridgeClientCtx
3884{
3885 SOCKET miner;
3886 std::string pool;
3887};
3888
3889static bool BridgeSendAll(SOCKET s, const char* p, int n)
3890{
3891 int off = 0;
3892 while (off < n)
3893 {
3894 int r = send(s, p + off, n - off, 0);
3895 if (r <= 0)
3896 return false;
3897 off += r;
3898 }
3899 return true;
3900}
3901
3902static void BridgePump(SOCKET a, SOCKET b)
3903{
3904 char buf[8192];
3905 while (!fShutdown)
3906 {
3907 fd_set rd;
3908 FD_ZERO(&rd);
3909 FD_SET(a, &rd);
3910 FD_SET(b, &rd);
3911 SOCKET maxfd = a > b ? a : b;
3912 struct timeval tv = {1, 0};
3913 int r = select((int)maxfd + 1, &rd, NULL, NULL, &tv);
3914 if (r <= 0)
3915 continue;
3916
3917 if (FD_ISSET(a, &rd))
3918 {
3919 int n = recv(a, buf, sizeof(buf), 0);
3920 if (n <= 0 || !BridgeSendAll(b, buf, n))
3921 break;
3922 }
3923 if (FD_ISSET(b, &rd))
3924 {
3925 int n = recv(b, buf, sizeof(buf), 0);
3926 if (n <= 0 || !BridgeSendAll(a, buf, n))
3927 break;
3928 }
3929 }
3930}
3931
3932static void ThreadStratumBridgeClient(void* arg)
3933{
3934 StratumBridgeClientCtx* ctx = (StratumBridgeClientCtx*)arg;
3935 SOCKET miner = ctx->miner;
3936 std::string pool = ctx->pool;
3937 delete ctx;
3938
3939 unsigned char target_pubkey[32];
3940 if (!btf::ParseAddress(pool, target_pubkey))
3941 {
3942 LogPrint("worker", "[bridge] invalid pool .btf address: %s\n", pool.c_str());
3943 BtfCloseSocket(miner);
3944 return;
3945 }
3946
3947 std::string meetingHostPort;
3948 unsigned char service_enc_pub[32];
3949 if (!BtfResolve(pool, meetingHostPort, service_enc_pub))
3950 {
3951 LogPrint("worker", "[bridge] failed to resolve pool %s\n", pool.c_str());
3952 BtfCloseSocket(miner);
3953 return;
3954 }
3955
3956 size_t colon = meetingHostPort.rfind(':');
3957 if (colon == std::string::npos)
3958 {
3959 LogPrint("worker", "[bridge] bad pool endpoint '%s'\n", meetingHostPort.c_str());
3960 BtfCloseSocket(miner);
3961 return;
3962 }
3963 std::string host = meetingHostPort.substr(0, colon);
3964 int port = atoi(meetingHostPort.substr(colon + 1).c_str());
3965 if (port <= 0 || port > 65535)
3966 {
3967 LogPrint("worker", "[bridge] bad pool port in '%s'\n", meetingHostPort.c_str());
3968 BtfCloseSocket(miner);
3969 return;
3970 }
3971
3972 SOCKET poolSock = btf::BtfClientTunnel(host.c_str(), (unsigned short)port,
3973 target_pubkey, service_enc_pub);
3974 if (poolSock == INVALID_SOCKET)
3975 {
3976 LogPrint("worker", "[bridge] tunnel connect failed for pool %s via %s\n",
3977 pool.c_str(), meetingHostPort.c_str());
3978 BtfCloseSocket(miner);
3979 return;
3980 }
3981
3982 LogPrint("worker", "[bridge] miner connected to pool %s via %s\n",
3983 pool.c_str(), meetingHostPort.c_str());
3984 BridgePump(miner, poolSock);
3985 BtfCloseSocket(poolSock);
3986 BtfCloseSocket(miner);
3987 LogPrint("worker", "[bridge] miner disconnected from pool %s\n", pool.c_str());
3988}
3989
3990void ThreadStratumBridge(void*)
3991{
3992 if (strParticipantPool.empty())
3993 {
3994 printf("Stratum bridge: no pool selected. Use /stratumbridge=POOL_BTF_ADDRESS\n");
3995 return;
3996 }
3997
3998 SOCKET listener = BtfSocketTag(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP),
3999 SOCK_STRATUM_BRIDGE);
4000 if (listener == INVALID_SOCKET)
4001 {
4002 printf("Stratum bridge: could not create listen socket\n");
4003 return;
4004 }
4005
4006 int yes = 1;
4007 setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
4008
4009 sockaddr_in addr;
4010 memset(&addr, 0, sizeof(addr));
4011 addr.sin_family = AF_INET;
4012 addr.sin_addr.s_addr = htonl(0x7f000001);
4013 addr.sin_port = htons((unsigned short)nStratumBridgePort);
4014
4015 if (bind(listener, (sockaddr*)&addr, sizeof(addr)) != 0 ||
4016 listen(listener, 16) != 0)
4017 {
4018 printf("Stratum bridge: could not listen on 127.0.0.1:%d\n",
4019 nStratumBridgePort);
4020 BtfCloseSocket(listener);
4021 return;
4022 }
4023
4024 printf("Stratum bridge: listening on 127.0.0.1:%d for pool %s\n",
4025 nStratumBridgePort, strParticipantPool.c_str());
4026
4027 while (!fShutdown)
4028 {
4029 fd_set rd;
4030 FD_ZERO(&rd);
4031 FD_SET(listener, &rd);
4032 struct timeval tv = {1, 0};
4033 if (select((int)listener + 1, &rd, NULL, NULL, &tv) <= 0)
4034 continue;
4035
4036 sockaddr_in cli;
4037#ifdef _WIN32
4038 int len = sizeof(cli);
4039#else
4040 socklen_t len = sizeof(cli);
4041#endif
4042 SOCKET miner = BtfSocketTag(accept(listener, (sockaddr*)&cli, &len),
4043 SOCK_STRATUM_BRIDGE);
4044 if (miner == INVALID_SOCKET)
4045 continue;
4046
4047 StratumBridgeClientCtx* ctx = new StratumBridgeClientCtx();
4048 ctx->miner = miner;
4049 ctx->pool = strParticipantPool;
4050 if (_beginthread(ThreadStratumBridgeClient, 0, ctx) == (uintptr_t)-1)
4051 {
4052 delete ctx;
4053 BtfCloseSocket(miner);
4054 LogPrint("worker", "[bridge] failed to spawn client thread\n");
4055 }
4056 }
4057
4058 BtfCloseSocket(listener);
4059 printf("Stratum bridge: stopped\n");
4060}
4061
3876bool BitcoinMiner(int nThreadId) 4062bool BitcoinMiner(int nThreadId)
3877{ 4063{
3878 // Relay mode: never mines, just relays/syncs. (Shouldn't normally get here 4064 // Relay mode: never mines, just relays/syncs. (Shouldn't normally get here