So, I made a list of tolerances within which private keys were found for all previous Bitcoin addresses, but still - too many, too large ranges even for the 71st. I want to understand how they solved the 125th and so on, its clear that the respected RetiredCoder didnt solve it by selection. The creator of the Bitcoin puzzle clearly used some kind of algorithm, but neither Mercer primes nor any prime number magic works.
31.01%
31.25%
31.67%
32.63%
33.49%
35.86%
38.33%
38.76%
36.39%
36.98%
平均値:34.6370000000000000000000000
下限許容範囲:-3.6270000000000000000000000
上限許容範囲:+2.3430000000000000000000000
リスト内の数量:10
50
50.18
51.49
51.57
53.13
57.2
平均値:52.2616666666666666666666666
下限許容範囲:-2.0816666666666666666666666
上限許容範囲:+4.9383333333333333333333334
リスト内の数量:6
40.23%
43.39%
43.41%
44.05%
45.35%
45.89%
46.11%
46.21%
49.01%
49.28%
平均値:45.2930000000000000000000000
下限許容範囲:-5.0630000000000000000000000
上限許容範囲:+3.9870000000000000000000000
リスト内の数量:10
70.06%
72%
72.78%
75%
75%
75.13%
77.03%
79.78%
平均値:74.5975000000000000000000000
下限許容範囲:-4.5375000000000000000000000
上限許容範囲:+5.1825000000000000000000000
リスト内の数量:8
82.17
82.42
82.56
82.56
82.86
82.89
87.25
平均値:83.2442857142857142857142857
下限許容範囲:-1.0742857142857142857142857
上限許容範囲:+4.0057142857142857142857143
リスト内の数量:7
22.73
23.36
23.67
25.62
27.34
28.71
28.87
平均値:25.7571428571428571428571428
下限許容範囲:-3.0271428571428571428571428
上限許容範囲:+3.1128571428571428571428572
リスト内の数量:7
62.2
62.54
63.98
64.4
64.53
64.66
65.71
66.18
66.79
66.82
67.98
68.48
69.5
69.6
平均値:65.9550000000000000000000000
下限許容範囲:-3.7550000000000000000000000
上限許容範囲:+3.6450000000000000000000000
リスト内の数量:14
91.85
92.44
92.98
95.01
95.8
96.9
97.8
平均値:94.6828571428571428571428571
下限許容範囲:-2.8328571428571428571428571
上限許容範囲:+3.1171428571428571428571429
リスト内の数量:7
17.07
17.77
18.75
19.32
平均値:18.2275000000000000000000000
下限許容範囲:-1.1575000000000000000000000
上限許容範囲:+1.0925000000000000000000000
リスト内の数量:4
0
0.39
0.72
6.94
8.56
平均値:3.3220000000000000000000000
下限許容範囲:-3.3220000000000000000000000
上限許容範囲:+5.2380000000000000000000000
リスト内の数量:5
9.03
10.74
12.79
13.67
平均値:11.5575000000000000000000000
下限許容範囲:-2.5275000000000000000000000
上限許容範囲:+2.1125000000000000000000000
リスト内の数量:4
100
リスト内の数量:1
これはまったくナンセンスだ。
Next, I found two programs, one for finding % relative to an array:
/* main.cpp
* Build: clang++ -std=c++11 -Iusr/local/include -Lusr/local/lib -lboost_system -lboost_filesystem main.cpp
* (Link flags not strictly required for header-only multiprecision)
* Requires Boost.Multiprecision (Boost 1.66 or similar)*/
#include <iostream>
#include <string>
#include <boost/multiprecision/cpp_int.hpp>
#include <iomanip>
using boost::multiprecision::cpp_int;
static cpp_int parse_hex(const std::string &s) {
std::string t = s;
if(t.size() >= 2 && t[0]=='0' && (t[1]=='x' || t[1]=='X')) t = t.substr(2);
cpp_int x = 0;
for(char c : t) {
x <<= 4;
if(c >= '0' && c <= '9') x += cpp_int(c - '0');
else if(c >= 'a' && c <= 'f') x += cpp_int(10 + c - 'a');
else if(c >= 'A' && c <= 'F') x += cpp_int(10 + c - 'A');
else {
std::cerr << "Invalid hex char: " << c << "\n";
exit(2);
}
}
return x;
}
static std::string to_hex(const cpp_int &x) {
if(x == 0) return "0x0";
cpp_int v = x;
std::string out;
while(v > 0) {
unsigned int nibble = static_cast<unsigned int>( (v & 0xF).convert_to<unsigned long>() );
char c = (nibble < 10) ? ('0' + nibble) : ('a' + (nibble - 10));
out.push_back(c);
v >>= 4;
}
std::reverse(out.begin(), out.end());
return std::string("0x") + out;
}
int main(int argc, char** argv) {
// argv: program start_hex end_hex percent1 percent2
// Examples:
// ./a.out 400000000000000000 7fffffffffffffffff 62.2 69.6
if(argc < 5) {
std::cerr << "Usage: " << argv[0] << " <start_hex> <end_hex> <pct1> <pct2>\n";
return 1;
}
cpp_int start = parse_hex(argv[1]);
cpp_int end = parse_hex(argv[2]);
// allow percents as decimals (e.g., 62.2)
auto parse_pct = [](const char* s) -> std::pair<cpp_int, cpp_int> {
// returns (numerator, denominator) as integers where percent = numerator/denominator
std::string t(s);
bool has_dot = false;
size_t pos = 0;
for(char c : t) if(c=='.') has_dot = true;
if(!has_dot) {
cpp_int num = 0;
for(char c : t) { if(c<'0'||c>'9') { std::cerr<<"Invalid percent: "<<t<<"\n"; exit(2);} num = num*10 + (c-'0'); }
return { num, cpp_int(100) };/ e.g., 62 -> 62/100
} else {
// convert decimal percent to fraction over 100 * 10^d
size_t dot = t.find('.');
std::string intpart = t.substr(0,dot);
std::string fracpart = t.substr(dot+1);
std::string all = intpart + fracpart;
cpp_int num = 0;
for(char c : all) { if(c<'0'||c>'9') { std::cerr<<"Invalid percent: "<<t<<"\n"; exit(2);} num = num*10 + (c-'0'); }
// denominator = 100 * 10^{frac_digits}
cpp_int denom = 100;
for(size_t i=0;i<fracpart.size();++i) denom *= 10;
return { num, denom };
}
};
auto p1 = parse_pct(argv[3]);
auto p2 = parse_pct(argv[4]);
// range width = end - start
if(end < start) { std::cerr << "End < Start\n"; return 2; }
cpp_int width = end - start;
// value = start + round(width * pct)
auto compute = [&](const cpp_int &num, const cpp_int &den) -> cpp_int {
// (width * num + den/2) den -> integer rounding
cpp_int prod = width * num;
cpp_int add = den 2;
cpp_int scaled = (prod + add) den;
return start + scaled;
};
cpp_int v1 = compute(p1.first, p1.second);
cpp_int v2 = compute(p2.first, p2.second);
*/ Output hex and decimal
std::cout << "start: " << to_hex(start) << " (" << start << ")\n";
std::cout << "end: " << to_hex(end) << " (" << end << ")\n\n";
std::cout << argv[3] << "% -> " << to_hex(v1) << " (" << v1 << ")\n";
std::cout << argv[4] << "% -> " << to_hex(v2) << " (" << v2 << ")\n";
*/
std::cout << argv[3] << "%:" << to_hex(v1) << "\n";
std::cout << argv[4] << "%:" << to_hex(v2) << "\n";
return 0;
}
foo$ ./a.out 0x444444 0x5534535 22.2 22.9
22.2%:0x163c1ea
22.9%:0x16cd290
Another one is for trying all the values, but that's all nonsense. Firstly, no one can guarantee that there will be matches even in the 14th range, and secondly, it would take me forever to calculate this on a Pentium M. (vanitygen++/vanitygen would also take a couple of billion years.) We need to understand the algorithm used to generate a series of private keys.
foo$ ./HEXGEN 0x163c1ea 0x163c1ed
000000000000000000000000000000000000000000000000000000000163c1ea
000000000000000000000000000000000000000000000000000000000163c1eb
000000000000000000000000000000000000000000000000000000000163c1ec
000000000000000000000000000000000000000000000000000000000163c1ed
foo$ cat main.cpp
/*clang++ -o HEXGEN -std=c++11 -I/usr/local/include -L/usr/local/lib main.cpp -lboost_system -lboost_filesystem*/
#include <iostream>
#include <string>
#include <boost/multiprecision/cpp_int.hpp>
#include <iomanip>
#include <sstream>
using boost::multiprecision::cpp_int;
using std::string;
// Parse hex string (with or without "0x") into cpp_int
cpp_int parse_hex(const string &s) {
string t = s;
if (t.size() >= 2 && t[0]=='0' && (t[1]=='x' || t[1]=='X')) t = t.substr(2);
// remove leading spaces
size_t p = t.find_first_not_of(" \t\n\r");
if (p!=string::npos) t = t.substr(p);
if (t.empty()) return cpp_int(0);
cpp_int r = 0;
for (char c : t) {
r <<= 4;
if (c>='0' && c<='9') r += cpp_int(c - '0');
else if (c>='a' && c<='f') r += cpp_int(10 + c - 'a');
else if (c>='A' && c<='F') r += cpp_int(10 + c - 'A');
else {
break;
}
}
return r;
}
string to_hex(const cpp_int &v) {
if (v == 0) return string("0");
cpp_int tmp = v;
std::string out;
while (tmp > 0) {
unsigned int nibble = static_cast<unsigned int>( (tmp & cpp_int(0xF)).convert_to<unsigned long>() );
char c = (nibble < 10 ? ('0' + nibble) : ('a' + (nibble - 10)));
out.push_back(c);
tmp >>= 4;
}
std::reverse(out.begin(), out.end());
return out;
}
int main(int argc, char** argv) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <start_hex> <end_hex>\n";
return 1;
}
cpp_int start = parse_hex(argv[1]);
cpp_int end = parse_hex(argv[2]);
if (start > end) {
std::cerr << "start must be <= end\n";
return 1;
}
// total width in hex digits for 128-bit = 32 hex chars; user requested 64 chars (implying 256-bit)
const size_t WIDTH = 64;
cpp_int cur = start;
while (cur <= end) {
string h = to_hex(cur);
if (h.size() < WIDTH) h = string(WIDTH - h.size(), '0') + h;
std::cout << h << "\n";
cur += 1;
}
return 0;
}OF course, after gen private keys, I in bash WHILE using HEX2WIF gens addresses, but, NO WORK.
So, I'm panicking; this is clearly beyond my student level. Any ideas about the algorithm? Although, yes, if someone had any, they would have become a millionaire long ago...
よろしくお願いいたします。Ada Sl|_|t。
