diff options
| author | Nsable-sh <nsable-sh@noreply.git.bitflash.network> | 2026-08-07 11:40:46 -0300 |
|---|---|---|
| committer | Bitflash <admin@bitflash.network> | 2026-08-07 15:05:18 -0300 |
| commit | 8c2e375600c0eb9bedb8f85ee4fa860825f23521 (patch) | |
| tree | 5701227e984e768ae9ed003f3447bff2dae92ee4 /src/rpc.cpp | |
| parent | 0b01d6cfce8be68150f5e06c11e13e0443372c4d (diff) | |
test: cover pool Stratum share accounting
Diffstat (limited to 'src/rpc.cpp')
| -rw-r--r-- | src/rpc.cpp | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/rpc.cpp b/src/rpc.cpp index 8f3740d..383769a 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp | |||
| @@ -1180,6 +1180,91 @@ static bool HandleLine(Miner* m, const std::string& rawLine, | |||
| 1180 | return true; | 1180 | return true; |
| 1181 | } | 1181 | } |
| 1182 | 1182 | ||
| 1183 | int RunPoolStratumSelfTest() | ||
| 1184 | { | ||
| 1185 | int nFail = 0; | ||
| 1186 | auto check = [&](bool ok, const char* msg) { | ||
| 1187 | fprintf(stdout, " %s %s\n", ok ? "ok" : "FAIL", msg); | ||
| 1188 | if (!ok) nFail++; | ||
| 1189 | }; | ||
| 1190 | |||
| 1191 | fprintf(stdout, "pool-stratum self-test\n"); | ||
| 1192 | |||
| 1193 | StratumJob savedJob = gCurrentJob; | ||
| 1194 | bool savedHaveJob = gHaveJob; | ||
| 1195 | |||
| 1196 | CTransaction coinbase; | ||
| 1197 | coinbase.vin.resize(1); | ||
| 1198 | coinbase.vin[0].prevout.SetNull(); | ||
| 1199 | coinbase.vin[0].scriptSig << 1 << (CBigNum)1; | ||
| 1200 | coinbase.vout.resize(1); | ||
| 1201 | coinbase.vout[0].nValue = 50 * COIN; | ||
| 1202 | |||
| 1203 | CBlock block; | ||
| 1204 | block.vtx.push_back(coinbase); | ||
| 1205 | block.nVersion = 1; | ||
| 1206 | block.nBits = 0x1f0fffff; | ||
| 1207 | block.nTime = 1; | ||
| 1208 | block.nNonce = 1; | ||
| 1209 | block.hashMerkleRoot = block.BuildMerkleTree(); | ||
| 1210 | |||
| 1211 | gCurrentJob.jobId = "selftest"; | ||
| 1212 | gCurrentJob.block = block; | ||
| 1213 | gCurrentJob.target = 0; // accepted share, not a block candidate | ||
| 1214 | gCurrentJob.height = 1; | ||
| 1215 | gHaveJob = true; | ||
| 1216 | |||
| 1217 | Miner miner(INVALID_SOCKET); | ||
| 1218 | miner.authorised = true; | ||
| 1219 | miner.address = "selftest-address"; | ||
| 1220 | miner.worker = "worker"; | ||
| 1221 | miner.shareTarget = ~uint256(0); // every RandomX hash is a valid share | ||
| 1222 | miner.difficulty = 0.001; | ||
| 1223 | miner.vardiffWindowStart = GetTime(); | ||
| 1224 | |||
| 1225 | std::map<std::string, uint64> roundShareCount; | ||
| 1226 | uint64 roundShareTotal = 0; | ||
| 1227 | int blocksFound = 0; | ||
| 1228 | |||
| 1229 | uint256 targetFromNotify; | ||
| 1230 | CBlock minerBlock = BuildMinerBlock(gCurrentJob, miner.extranonce2); | ||
| 1231 | json params = MakeNotifyParams(gCurrentJob, minerBlock, miner.shareTarget, true); | ||
| 1232 | std::vector<unsigned char> targetBytes = FromHex(params[3].get<std::string>()); | ||
| 1233 | if (targetBytes.size() == 32) | ||
| 1234 | memcpy(&targetFromNotify, &targetBytes[0], 32); | ||
| 1235 | check(targetFromNotify == miner.shareTarget, | ||
| 1236 | "mining.notify exposes the same share target the pool validates"); | ||
| 1237 | |||
| 1238 | json submit = { | ||
| 1239 | {"id", 7}, | ||
| 1240 | {"method", "mining.submit"}, | ||
| 1241 | {"params", json::array({miner.address, "selftest", ToHex(&minerBlock.nNonce, 4)})} | ||
| 1242 | }; | ||
| 1243 | HandleLine(&miner, submit.dump(), roundShareCount, roundShareTotal, blocksFound); | ||
| 1244 | |||
| 1245 | check(roundShareTotal == 1, "fake low-difficulty share increments the round total"); | ||
| 1246 | check(roundShareCount[miner.address] == 1, "fake share is credited to the submitting address"); | ||
| 1247 | check(miner.sessionShares == 1 && miner.roundShares == 1 && miner.totalShares == 1, | ||
| 1248 | "miner share counters advance together"); | ||
| 1249 | check(blocksFound == 0, "share below block target is not counted as a found block"); | ||
| 1250 | |||
| 1251 | json stale = { | ||
| 1252 | {"id", 8}, | ||
| 1253 | {"method", "mining.submit"}, | ||
| 1254 | {"params", json::array({miner.address, "stale", ToHex(&minerBlock.nNonce, 4)})} | ||
| 1255 | }; | ||
| 1256 | HandleLine(&miner, stale.dump(), roundShareCount, roundShareTotal, blocksFound); | ||
| 1257 | check(roundShareTotal == 1, "stale submit does not increment shares"); | ||
| 1258 | |||
| 1259 | gCurrentJob = savedJob; | ||
| 1260 | gHaveJob = savedHaveJob; | ||
| 1261 | |||
| 1262 | fprintf(stdout, "%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", | ||
| 1263 | nFail, nFail == 1 ? "" : "s"); | ||
| 1264 | fflush(stdout); | ||
| 1265 | return nFail == 0 ? 0 : 1; | ||
| 1266 | } | ||
| 1267 | |||
| 1183 | // --------------------------------------------------------------------------- | 1268 | // --------------------------------------------------------------------------- |
| 1184 | // Stats refresh -- called every 2s from event loop | 1269 | // Stats refresh -- called every 2s from event loop |
| 1185 | // --------------------------------------------------------------------------- | 1270 | // --------------------------------------------------------------------------- |