DILSHAD737 commited on
Commit
cd31d24
·
1 Parent(s): 03721e4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +16 -194
app.py CHANGED
@@ -1,198 +1,20 @@
1
- from itertools import permutations, combinations
2
- import hashlib, hmac, os, time, math, gc
3
  from multiprocessing import Pool
4
- from eth_account import Account
5
- import coincurve
6
- from eth_utils import keccak, to_checksum_address
7
 
8
- Account.enable_unaudited_hdwallet_features()
9
- # ============================================================
10
- words = [
11
- "lesson", "cushion", "crane", "affair", "federal",
12
- "decline", "limb", "spend", "reunion", "chief", "cart", "zebra",
13
- ]
14
-
15
- PHRASE_MODE = "order"
16
- USE_BIP39 = False
17
- BIP39_PASSPHRASE = ""
18
- HD_DERIVATION = True
19
- ADDRESS_INDEX = 0
20
- CHECK_BIP39_CHECKSUM = False
21
- ADDRESSES_FILE = "12730802_addresses.csv"
22
- BATCH_SIZE = 5000
23
- NUM_WORKERS = 96
24
- # ============================================================
25
-
26
- # ---------- BIP32 (same as before) ----------
27
- _SECP256K1_N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
28
- _HARDENED = 0x80000000
29
-
30
- def _bip32_derive_child_priv(parent_priv, parent_chain, index):
31
- if index >= _HARDENED:
32
- data = b'\x00' + parent_priv + index.to_bytes(4, 'big')
33
- else:
34
- pub = coincurve.PrivateKey(parent_priv).public_key.format(compressed=True)
35
- data = pub + index.to_bytes(4, 'big')
36
- I = hmac.new(parent_chain, data, hashlib.sha512).digest()
37
- child_int = (int.from_bytes(I[:32], 'big') + int.from_bytes(parent_priv, 'big')) % _SECP256K1_N
38
- if child_int == 0:
39
- raise ValueError("Invalid child key")
40
- return child_int.to_bytes(32, 'big'), I[32:]
41
-
42
- def seed_to_privkey_hd(seed, address_index=0):
43
- I = hmac.new(b"Bitcoin seed", seed, hashlib.sha512).digest()
44
- key, chain = I[:32], I[32:]
45
- path = [44 + _HARDENED, 60 + _HARDENED, _HARDENED, 0, address_index]
46
- for idx in path:
47
- key, chain = _bip32_derive_child_priv(key, chain, idx)
48
- return key
49
-
50
- # ---------- BIP39 ----------
51
- try:
52
- import bip39 as _bip39_rust
53
- _USE_RUST_BIP39 = True
54
- except ImportError:
55
- _bip39_rust = None
56
- _USE_RUST_BIP39 = False
57
-
58
- _MNEMONIC = None
59
-
60
- def _get_mnemonic():
61
- global _MNEMONIC
62
- if _MNEMONIC is None:
63
- from mnemonic import Mnemonic
64
- _MNEMONIC = Mnemonic("english")
65
- return _MNEMONIC
66
-
67
- def is_valid_bip39_fast(phrase):
68
- return _get_mnemonic().check(phrase)
69
-
70
- def phrase_to_seed(phrase):
71
- if _USE_RUST_BIP39:
72
- return _bip39_rust.bip39_mnemonic_to_seed(phrase, BIP39_PASSPHRASE)
73
- return _get_mnemonic().to_seed(phrase, passphrase=BIP39_PASSPHRASE)
74
-
75
- # ---------- Address file ----------
76
- def load_addresses(path):
77
- s = set()
78
- with open(path, "r", encoding="utf-8") as f:
79
- for line in f:
80
- a = line.strip().strip('"').strip("'").lstrip("\ufeff").lower()
81
- if a.startswith("0x"):
82
- a = a[2:]
83
- if a and len(a) == 40:
84
- s.add(a)
85
- return frozenset(s)
86
-
87
- def normalize(addr):
88
- a = addr.strip().lower()
89
- if a.startswith("0x"):
90
- a = a[2:]
91
- return a
92
-
93
- # ---------- Generator ----------
94
- def generate_phrases():
95
- n = len(words)
96
- if PHRASE_MODE == "order":
97
- for perm in permutations(words):
98
- yield " ".join(perm)
99
- elif PHRASE_MODE == "replace":
100
- for i in range(n):
101
- for w in words:
102
- new = words.copy()
103
- new[i] = w
104
- yield " ".join(new)
105
- elif PHRASE_MODE == "subset":
106
- for r in range(1, n + 1):
107
- for combo in combinations(words, r):
108
- yield " ".join(combo)
109
-
110
- def count_total():
111
- n = len(words)
112
- if PHRASE_MODE == "order": return math.factorial(n)
113
- if PHRASE_MODE == "replace": return n * n
114
- if PHRASE_MODE == "subset": return 2**n - 1
115
-
116
- # ---------- Worker ----------
117
- _KNOWN = None
118
-
119
- def init_worker(known):
120
- global _KNOWN
121
- _KNOWN = known
122
- _get_mnemonic()
123
-
124
- def process_batch(batch):
125
- hits = []
126
- known = _KNOWN
127
- for phrase in batch:
128
- try:
129
- acct = Account.from_mnemonic(
130
- phrase,
131
- passphrase=BIP39_PASSPHRASE,
132
- account_path=f"m/44'/60'/0'/0/{ADDRESS_INDEX}"
133
- )
134
- addr = acct.address
135
- priv = acct.key
136
- except Exception as e:
137
- # print(f"❌ Exception: {e}")
138
- continue
139
-
140
- normalized = normalize(addr)
141
- if normalized in known:
142
- hits.append((phrase, priv.hex(), addr))
143
- return hits
144
-
145
- def batch_generator():
146
- batch = []
147
- for phrase in generate_phrases():
148
- batch.append(phrase)
149
- if len(batch) >= BATCH_SIZE:
150
- yield batch
151
- batch = []
152
- if batch:
153
- yield batch
154
-
155
- # ---------- Main ----------
156
- def main():
157
- if not os.path.exists(ADDRESSES_FILE):
158
- raise SystemExit(f"File nahi mili: {ADDRESSES_FILE}")
159
-
160
- total = count_total()
161
- print(f"\nMode: {PHRASE_MODE} | Total: {total:,} | Workers: {NUM_WORKERS}")
162
- print(f"HD: {HD_DERIVATION} (index {ADDRESS_INDEX})")
163
- print(f"Checksum prefilter: {CHECK_BIP39_CHECKSUM}\n")
164
-
165
- known = load_addresses(ADDRESSES_FILE)
166
- print(f"Loaded {len(known):,} addresses\n")
167
-
168
- matches = []
169
- done = 0
170
- start = time.time()
171
- last_log = start
172
-
173
- gc.collect()
174
- gc.freeze()
175
-
176
- with Pool(processes=NUM_WORKERS,
177
- initializer=init_worker,
178
- initargs=(known,),
179
- maxtasksperchild=1000) as pool:
180
- for hits in pool.imap_unordered(process_batch, batch_generator(), chunksize=10):
181
- done += BATCH_SIZE
182
- for phrase, key_hex, addr in hits:
183
- print(f"\n✅ MATCH: {phrase}\n priv: {key_hex}\n addr: {addr}\n")
184
- matches.append((phrase, key_hex, addr))
185
-
186
- now = time.time()
187
- if now - last_log >= 2:
188
- elapsed = now - start
189
- rate = done / elapsed if elapsed else 0
190
- eta = (total - done) / rate if rate else 0
191
- print(f" ...{done:,}/{total:,} ({100*done/total:.1f}%) ETA {eta:.0f}s")
192
- last_log = now
193
-
194
- elapsed = time.time() - start
195
- print(f"\nDone {elapsed:.1f}s. {len(matches)} match(es).")
196
 
197
  if __name__ == "__main__":
198
- main()
 
 
 
 
 
 
 
1
+ import time
 
2
  from multiprocessing import Pool
 
 
 
3
 
4
+ def work(n):
5
+ # BIP39 PBKDF2 simulation
6
+ from mnemonic import Mnemonic
7
+ m = Mnemonic("english")
8
+ phrase = "lesson cushion crane affair federal decline limb spend reunion chief cart zebra"
9
+ for _ in range(n):
10
+ m.to_seed(phrase)
11
+ return n
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  if __name__ == "__main__":
14
+ for workers in [48, 96, 192]:
15
+ with Pool(workers) as p:
16
+ start = time.time()
17
+ p.map(work, [10] * workers)
18
+ elapsed = time.time() - start
19
+ rate = (workers * 10) / elapsed
20
+ print(f"{workers} workers: {rate:,.0f} phrases/sec")