upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp186
-rw-r--r--src/main.h3
-rw-r--r--src/main_gui.cpp22
-rw-r--r--src/net.cpp2
-rw-r--r--src/readme.txt5
-rw-r--r--src/sockcount.h1
6 files changed, 218 insertions, 1 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
diff --git a/src/main.h b/src/main.h
index 3866855..2786a4a 100644
--- a/src/main.h
+++ b/src/main.h
@@ -88,6 +88,8 @@ extern string strPoolName; // operator: announced pool name
88extern string strPoolDashboardUrl; // operator: optional dashboard URL 88extern string strPoolDashboardUrl; // operator: optional dashboard URL
89extern string strPoolStatusFile; // operator: optional JSON status output path 89extern string strPoolStatusFile; // operator: optional JSON status output path
90extern double dPoolFeePercent; // operator: announced fee percent 90extern double dPoolFeePercent; // operator: announced fee percent
91extern bool fStratumBridge; // participant helper: local Stratum bridge
92extern int nStratumBridgePort; // local bridge listen port, default 3333
91extern bool fSoloMineTest; // /solomine: mine without requiring a peer (local test) 93extern bool fSoloMineTest; // /solomine: mine without requiring a peer (local test)
92// Threads to hash with; 0 = decide from the hardware. Set by /genproclimit. 94// Threads to hash with; 0 = decide from the hardware. Set by /genproclimit.
93extern int nMinerThreads; 95extern int nMinerThreads;
@@ -272,6 +274,7 @@ void LimitOrphanBlocks(unsigned int nMaxOrphans);
272// distinguishable, which the dedup filter would otherwise collapse into one. 274// distinguishable, which the dedup filter would otherwise collapse into one.
273bool BitcoinMiner(int nThreadId = 1); 275bool BitcoinMiner(int nThreadId = 1);
274void ThreadRPCServer(void* parg); // rpc.cpp -- .btf pool server 276void ThreadRPCServer(void* parg); // rpc.cpp -- .btf pool server
277void ThreadStratumBridge(void* parg); // main.cpp -- local Stratum -> .btf bridge
275void GetParticipantMiningStats(uint64& sharesSent, uint64& sharesAccepted, double& hashRate); 278void GetParticipantMiningStats(uint64& sharesSent, uint64& sharesAccepted, double& hashRate);
276void SetParticipantMiningStatus(const std::string& status); 279void SetParticipantMiningStatus(const std::string& status);
277std::string GetParticipantMiningStatus(); 280std::string GetParticipantMiningStatus();
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 41661b9..ce6d2b5 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -115,6 +115,8 @@ static void PrintUsage()
115 printf("Mining mode:\n"); 115 printf("Mining mode:\n");
116 printf(" /operator\n"); 116 printf(" /operator\n");
117 printf(" /participant=POOL_BTF_ADDRESS\n"); 117 printf(" /participant=POOL_BTF_ADDRESS\n");
118 printf(" /stratumbridge=POOL_BTF_ADDRESS\n");
119 printf(" /stratumbridgeport=N (default 3333; listen on 127.0.0.1)\n");
118 printf(" /solomine\n"); 120 printf(" /solomine\n");
119 printf(" /genproclimit=N (mining threads; 0 or absent = every core but one)\n"); 121 printf(" /genproclimit=N (mining threads; 0 or absent = every core but one)\n");
120 printf(" /checkblocks=N (blocks re-verified at startup, default 288, 0 = all)\n"); 122 printf(" /checkblocks=N (blocks re-verified at startup, default 288, 0 = all)\n");
@@ -226,6 +228,22 @@ static void ParseStartupArguments(int argc, char* argv[])
226 fMineModeFromCommandLine = true; 228 fMineModeFromCommandLine = true;
227 } 229 }
228 230
231 if (arg(argc,argv,"/stratumbridge") || arg(argc,argv,"-stratumbridge"))
232 {
233 fStratumBridge = true;
234 string bridgePool = argval2(argc, argv, "/stratumbridge", "-stratumbridge");
235 if (!bridgePool.empty())
236 strParticipantPool = bridgePool;
237 }
238
239 string bridgePort = argval2(argc, argv, "/stratumbridgeport", "-stratumbridgeport");
240 if (!bridgePort.empty())
241 {
242 int nPort = atoi(bridgePort.c_str());
243 if (nPort > 0 && nPort <= 65535)
244 nStratumBridgePort = nPort;
245 }
246
229 string poolName = argval2(argc, argv, "/poolname", "-poolname"); 247 string poolName = argval2(argc, argv, "/poolname", "-poolname");
230 if (!poolName.empty()) 248 if (!poolName.empty())
231 strPoolName = poolName; 249 strPoolName = poolName;
@@ -623,6 +641,10 @@ int main(int argc, char* argv[])
623 if (_beginthread(ThreadRPCServer, 0, NULL) == (uintptr_t)-1) 641 if (_beginthread(ThreadRPCServer, 0, NULL) == (uintptr_t)-1)
624 printf("Error: _beginthread(ThreadRPCServer) failed\n"); 642 printf("Error: _beginthread(ThreadRPCServer) failed\n");
625 } 643 }
644 if (fStratumBridge) {
645 if (_beginthread(ThreadStratumBridge, 0, NULL) == (uintptr_t)-1)
646 printf("Error: _beginthread(ThreadStratumBridge) failed\n");
647 }
626 if (fGenerateBitcoins) 648 if (fGenerateBitcoins)
627 StartMinerThreads(); 649 StartMinerThreads();
628 650
diff --git a/src/net.cpp b/src/net.cpp
index 449d91c..b9bb95d 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -153,7 +153,7 @@ static const char* pszSockSite[SOCK_SITES] = {
153 "external-ip probe", "listen socket", "inbound accept", 153 "external-ip probe", "listen socket", "inbound accept",
154 "rendezvous dial", "rendezvous listen", "rendezvous accept", 154 "rendezvous dial", "rendezvous listen", "rendezvous accept",
155 "loopback pair listener", "loopback pair app end", "loopback pair pump end", 155 "loopback pair listener", "loopback pair app end", "loopback pair pump end",
156 "nostr relay" 156 "nostr relay", "stratum bridge"
157}; 157};
158 158
159static string SockAccountingText() 159static string SockAccountingText()
diff --git a/src/readme.txt b/src/readme.txt
index 6af1694..fa58b6e 100644
--- a/src/readme.txt
+++ b/src/readme.txt
@@ -46,6 +46,11 @@ Command-line options (in addition to the original ones)
46 /operator operator mode (run pool server) 46 /operator operator mode (run pool server)
47 /participant=ADDR 47 /participant=ADDR
48 participant mode; mine to pool .btf address ADDR 48 participant mode; mine to pool .btf address ADDR
49 /stratumbridge=ADDR
50 listen on 127.0.0.1:3333 and bridge external Stratum miners
51 to pool .btf address ADDR
52 /stratumbridgeport=N
53 local Stratum bridge port (default 3333)
49 /poolname=NAME operator announcement pool name 54 /poolname=NAME operator announcement pool name
50 /poolfee=PCT operator announcement fee percent (example: 0.75) 55 /poolfee=PCT operator announcement fee percent (example: 0.75)
51 /pooldashboard=URL 56 /pooldashboard=URL
diff --git a/src/sockcount.h b/src/sockcount.h
index 96b6efb..5147f55 100644
--- a/src/sockcount.h
+++ b/src/sockcount.h
@@ -63,6 +63,7 @@ enum
63 SOCK_PAIR_APP, // loopback pair: the app end handed to CNode 63 SOCK_PAIR_APP, // loopback pair: the app end handed to CNode
64 SOCK_PAIR_PUMP, // loopback pair: the pump end 64 SOCK_PAIR_PUMP, // loopback pair: the pump end
65 SOCK_NOSTR, // outbound to a Nostr relay 65 SOCK_NOSTR, // outbound to a Nostr relay
66 SOCK_STRATUM_BRIDGE, // local Stratum bridge listener/miner sockets
66 SOCK_SITES 67 SOCK_SITES
67}; 68};
68 69