Summary
Exceeding the documented 125-bit interval limit does not fail. It produces wrong private keys with no error, no warning and no crash, while reporting normal progress the whole time.
The README states the limit ("This program is limited to a 125bit interval search") but not the failure mode, so a run above it looks healthy and its output is worthless. Related: #154, #122.
Cause
HashTable.h packs the travelled distance into 128 bits:
typedef struct {
int128_t x; // Poisition of kangaroo (128bit LSB)
int128_t d; // Travelled distance (b127=sign b126=kangaroo type, b125..b0 distance
} ENTRY;
126 bits of magnitude. Distances span the interval width, so a wider interval overflows — and HashTable::Convert() masks the excess away rather than rejecting it:
D->i64[1] = d->bits64[1] & 0x3FFFFFFFFFFFFFFFULL;
The entry is then indistinguishable from a valid one. On collision it yields a wrong key.
Reproduce
Puzzle #140's published range and public key (2^139 interval):
80000000000000000000000000000000000
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
031F6A332D3C5C4F2DE2378C012F429CD109BA07D69690C6C701B6BB87860D6640
./kangaroo -gpu -d 16 -w w140.kcp -wi 20 in140.txt # let it run, then stop
./kangaroo -t 4 -wcheck w140.kcp
Result on current master:
| interval |
DPs stored |
-wcheck |
| 2^119 (#120) |
17,088 |
100.000% OK |
| 2^139 (#140) |
376,836 |
0.024% OK — 376,747 corrupt |
2^119 is inside the cap and is fine, so this is specifically the over-limit path. Nothing in the 2^139 run's output distinguishes it from the 2^119 run.
Why it matters
Every currently unsolved kangaroo-able puzzle is above the limit — #135 is a 2^134 interval, #140 is 2^139 — so anyone pointing this tool at them today is accumulating corrupt data and cannot tell.
Note for anyone arriving from #154
Chunking the range into sub-intervals below the cap is correct, but expensive. Kangaroo costs ~K·√W, so splitting W into m chunks costs m·K·√(W/m) = √m times more work. The 512 chunks suggested in #154 is √512 ≈ 23× the work of searching 2^134 in one pass. It is a workaround, not a fix.
Fix
PR #158 widens the distance field to 256 bits (254 bits of magnitude, intervals to 253 bits) and makes over-range distances exit(-1) instead of truncating. Same input as above: 100.000% OK. It also fixes a CUDA 13 build break — cudaDeviceProp::computeMode was removed, so GPUEngine.cu does not compile against a current toolkit at all.
Minimal alternative if the format change is unwanted: add a startup check that refuses an interval wider than 125 bits. Failing loudly costs nothing and turns silently-wrong output into an error message.
🤖 Generated with Claude Code
Summary
Exceeding the documented 125-bit interval limit does not fail. It produces wrong private keys with no error, no warning and no crash, while reporting normal progress the whole time.
The README states the limit ("This program is limited to a 125bit interval search") but not the failure mode, so a run above it looks healthy and its output is worthless. Related: #154, #122.
Cause
HashTable.hpacks the travelled distance into 128 bits:126 bits of magnitude. Distances span the interval width, so a wider interval overflows — and
HashTable::Convert()masks the excess away rather than rejecting it:The entry is then indistinguishable from a valid one. On collision it yields a wrong key.
Reproduce
Puzzle #140's published range and public key (2^139 interval):
Result on current
master:-wcheck2^119 is inside the cap and is fine, so this is specifically the over-limit path. Nothing in the 2^139 run's output distinguishes it from the 2^119 run.
Why it matters
Every currently unsolved kangaroo-able puzzle is above the limit — #135 is a 2^134 interval, #140 is 2^139 — so anyone pointing this tool at them today is accumulating corrupt data and cannot tell.
Note for anyone arriving from #154
Chunking the range into sub-intervals below the cap is correct, but expensive. Kangaroo costs ~K·√W, so splitting W into m chunks costs m·K·√(W/m) = √m times more work. The 512 chunks suggested in #154 is √512 ≈ 23× the work of searching 2^134 in one pass. It is a workaround, not a fix.
Fix
PR #158 widens the distance field to 256 bits (254 bits of magnitude, intervals to 253 bits) and makes over-range distances
exit(-1)instead of truncating. Same input as above: 100.000% OK. It also fixes a CUDA 13 build break —cudaDeviceProp::computeModewas removed, soGPUEngine.cudoes not compile against a current toolkit at all.Minimal alternative if the format change is unwanted: add a startup check that refuses an interval wider than 125 bits. Failing loudly costs nothing and turns silently-wrong output into an error message.
🤖 Generated with Claude Code