-
Notifications
You must be signed in to change notification settings - Fork 6
/
fixup.d
executable file
·79 lines (66 loc) · 1.4 KB
/
fixup.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env rdmd
module fixup;
string rebuildAddr(const ubyte[] data) {
string ret;
ret.reserve(data.length);
size_t i = 0;
while (data[i]) {
enum Base = 'a' & 0xe0;
ret ~= cast(char) (Base + data[i++]);
}
ret ~= ':';
foreach (c; data[i + 1 .. $]) {
import util.base32;
ret ~= getBech32(c);
}
return ret;
}
string fixCashAddr(string addr) {
ubyte[] data;
size_t prefixSize;
import cashaddr;
if (!decodeData(addr, prefixSize, data)) {
return "";
}
import util.bch;
ulong checksum = polyMod(data);
if (checksum == 0) {
return rebuildAddr(data);
}
/**
* Ok, it gets interesting now, we have a checksum that do not match.
* We start by computing the syndromes and try to find a set of error
* that fixes the address.
*/
ulong[ulong] syndromes;
foreach (p; 0 .. data.length) {
foreach(e; 1 .. 32) {
// Add the error;
data[p] ^= e;
scope(success) data[p] ^= e;
ulong c = polyMod(data);
if (c == 0) {
return rebuildAddr(data);
}
syndromes[c ^ checksum] = p * 32 + e;
}
}
foreach (s0, pe; syndromes) {
if (auto s1ptr = (s0 ^ checksum) in syndromes) {
data[pe / 32] ^= pe % 32;
data[*s1ptr / 32] ^= *s1ptr % 32;
return rebuildAddr(data);
}
}
// We failed to fix.
return "";
}
void main(string[] addrs) {
foreach (a; addrs[1 .. $]) {
auto fixed = fixCashAddr(a);
if (fixed) {
import std.stdio;
writeln(fixed);
}
}
}