DILSHAD737 commited on
Commit
a41694f
Β·
1 Parent(s): 811e503

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +213 -26
app.py CHANGED
@@ -1,16 +1,29 @@
1
- # debug_derive.py
2
- import hashlib, hmac
 
3
  from eth_account import Account
4
- from mnemonic import Mnemonic
5
- from eth_utils import keccak, to_checksum_address
6
  import coincurve
 
7
 
8
- Account.enable_unaudited_hdwallet_features()
 
 
 
 
9
 
10
- phrase = "lesson cushion crane affair federal decline limb spend reunion chief cart zebra"
11
- TARGET = "0x3f0482fc3e9132c3d3acb5f588e980d7b3a5af07"
 
 
 
 
 
 
 
 
 
12
 
13
- # --- 1. Aapka manual BIP32 code (jo aapke script mein hai) ---
14
  _SECP256K1_N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
15
  _HARDENED = 0x80000000
16
 
@@ -34,21 +47,195 @@ def seed_to_privkey_hd(seed, address_index=0):
34
  key, chain = _bip32_derive_child_priv(key, chain, idx)
35
  return key
36
 
37
- # --- 2. Manual derivation se address ---
38
- seed = Mnemonic("english").to_seed(phrase, passphrase="")
39
- priv_manual = seed_to_privkey_hd(seed, 0)
40
- pub_manual = coincurve.PrivateKey(priv_manual).public_key.format(compressed=False)[1:]
41
- addr_manual = to_checksum_address(keccak(pub_manual)[-20:])
42
-
43
- # --- 3. eth_account se address ---
44
- acct = Account.from_mnemonic(phrase, account_path="m/44'/60'/0'/0/0")
45
- addr_standard = acct.address
46
-
47
- # --- 4. Result ---
48
- print(f"Manual BIP32: {addr_manual}")
49
- print(f"eth_account: {addr_standard}")
50
- print(f"Target: {TARGET}")
51
- print()
52
- print(f"Manual == Target: {addr_manual.lower() == TARGET.lower()}")
53
- print(f"eth_account == Target: {addr_standard.lower() == TARGET.lower()}")
54
- print(f"Manual == eth_account: {addr_manual.lower() == addr_standard.lower()}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # ============================================================
9
+ words = [
10
+ "lesson", "cushion", "crane", "affair", "federal",
11
+ "decline", "limb", "spend", "reunion", "chief", "cart", "zebra",
12
+ ]
13
 
14
+ PHRASE_MODE = "replace"
15
+ USE_BIP39 = True
16
+ BIP39_PASSPHRASE = ""
17
+ HD_DERIVATION = True
18
+ ADDRESS_INDEX = 0
19
+ CHECK_BIP39_CHECKSUM = True
20
+ ADDRESSES_FILE = "12730802_addresses.csv"
21
+ MATCHED_FILE = f"matched_keys_{PHRASE_MODE}.txt"
22
+ BATCH_SIZE = 500
23
+ NUM_WORKERS = 96
24
+ # ============================================================
25
 
26
+ # ---------- secp256k1 ----------
27
  _SECP256K1_N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
28
  _HARDENED = 0x80000000
29
 
 
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
+ if _USE_RUST_BIP39:
69
+ try:
70
+ _bip39_rust.bip39_mnemonic_to_entropy(phrase)
71
+ return True
72
+ except Exception:
73
+ return False
74
+ return _get_mnemonic().check(phrase)
75
+
76
+ def phrase_to_seed(phrase):
77
+ if _USE_RUST_BIP39:
78
+ return _bip39_rust.bip39_mnemonic_to_seed(phrase, BIP39_PASSPHRASE)
79
+ return _get_mnemonic().to_seed(phrase, passphrase=BIP39_PASSPHRASE)
80
+
81
+ # ---------- Address file ----------
82
+ def load_addresses(path):
83
+ s = set()
84
+ with open(path, "r", encoding="utf-8") as f:
85
+ for line in f:
86
+ a = line.strip().strip('"').strip("'").lstrip("\ufeff").lower()
87
+ if a.startswith("0x"):
88
+ a = a[2:]
89
+ if a and len(a) == 40:
90
+ s.add(a)
91
+ return frozenset(s)
92
+
93
+ def normalize(addr):
94
+ a = addr.strip().lower()
95
+ if a.startswith("0x"):
96
+ a = a[2:]
97
+ return a
98
+
99
+ # ---------- Generator ----------
100
+ def generate_phrases():
101
+ n = len(words)
102
+ if PHRASE_MODE == "order":
103
+ for perm in permutations(words):
104
+ yield " ".join(perm)
105
+ elif PHRASE_MODE == "replace":
106
+ for i in range(n):
107
+ for w in words:
108
+ new = words.copy()
109
+ new[i] = w
110
+ yield " ".join(new)
111
+ elif PHRASE_MODE == "subset":
112
+ for r in range(1, n + 1):
113
+ for combo in combinations(words, r):
114
+ yield " ".join(combo)
115
+
116
+ def count_total():
117
+ n = len(words)
118
+ if PHRASE_MODE == "order": return math.factorial(n)
119
+ if PHRASE_MODE == "replace": return n * n
120
+ if PHRASE_MODE == "subset": return 2**n - 1
121
+
122
+ # ---------- Worker ----------
123
+ _KNOWN = None
124
+
125
+ def init_worker(known):
126
+ global _KNOWN
127
+ _KNOWN = known
128
+ _get_mnemonic()
129
+ # βœ… DEBUG: worker init confirm
130
+ print(f"πŸ”§ Worker init: known size = {len(known):,}")
131
+ target = "3f0482fc3e9132c3d3acb5f588e980d7b3a5af07"
132
+ print(f" target in known: {target in known}")
133
+
134
+ def process_batch(batch):
135
+ hits = []
136
+ known = _KNOWN
137
+ m = _get_mnemonic()
138
+ for phrase in batch:
139
+ # βœ… DEBUG: har phrase print (sirf pehle 5, taake output flood na ho)
140
+ if process_batch.counter < 5:
141
+ print(f"πŸ” Process phrase: {phrase}")
142
+ process_batch.counter += 1
143
+
144
+ if CHECK_BIP39_CHECKSUM and not is_valid_bip39_fast(phrase):
145
+ if process_batch.counter <= 5:
146
+ print(f" ❌ Checksum fail: {phrase}")
147
+ continue
148
+ try:
149
+ seed = phrase_to_seed(phrase)
150
+ if HD_DERIVATION:
151
+ priv = seed_to_privkey_hd(seed, ADDRESS_INDEX)
152
+ else:
153
+ priv = seed[:32]
154
+ pub = coincurve.PrivateKey(priv).public_key.format(compressed=False)[1:]
155
+ addr = to_checksum_address(keccak(pub)[-20:])
156
+ except Exception as e:
157
+ if process_batch.counter <= 5:
158
+ print(f" ❌ Error: {e}")
159
+ continue
160
+
161
+ normalized = normalize(addr)
162
+ if process_batch.counter <= 5:
163
+ print(f" addr: {addr}")
164
+ print(f" normalized: {normalized}")
165
+ print(f" in known: {normalized in known}")
166
+ if phrase == "lesson cushion crane affair federal decline limb spend reunion chief cart zebra":
167
+ target = "3f0482fc3e9132c3d3acb5f588e980d7b3a5af07"
168
+ print(f" target: {target}")
169
+ print(f" equal: {normalized == target}")
170
+
171
+ if normalized in known:
172
+ hits.append((phrase, priv.hex(), addr))
173
+ return hits
174
+
175
+ # Counter attribute (multiprocessing mein kaam karega? nahi, lekin debug ke liye)
176
+ process_batch.counter = 0
177
+
178
+ def batch_generator():
179
+ batch = []
180
+ for phrase in generate_phrases():
181
+ batch.append(phrase)
182
+ if len(batch) >= BATCH_SIZE:
183
+ yield batch
184
+ batch = []
185
+ if batch:
186
+ yield batch
187
+
188
+ # ---------- Main ----------
189
+ def main():
190
+ if not os.path.exists(ADDRESSES_FILE):
191
+ raise SystemExit(f"File nahi mili: {ADDRESSES_FILE}")
192
+
193
+ total = count_total()
194
+ print(f"\nMode: {PHRASE_MODE} | Total: {total:,} | Workers: {NUM_WORKERS}")
195
+ print(f"HD: {HD_DERIVATION} (index {ADDRESS_INDEX})\n")
196
+
197
+ known = load_addresses(ADDRESSES_FILE)
198
+ print(f"Loaded {len(known):,} lowercase addresses\n")
199
+
200
+ # βœ… DEBUG: pehla phrase check
201
+ first_phrase = next(generate_phrases())
202
+ print(f"First phrase generated: {first_phrase}")
203
+ print(f"Target phrase: {repr('lesson cushion crane affair federal decline limb spend reunion chief cart zebra')}")
204
+ print(f"Match: {first_phrase == 'lesson cushion crane affair federal decline limb spend reunion chief cart zebra'}\n")
205
+
206
+ matches = []
207
+ done = 0
208
+ start = time.time()
209
+ last_log = start
210
+
211
+ if os.path.exists(MATCHED_FILE):
212
+ os.remove(MATCHED_FILE)
213
+
214
+ gc.collect()
215
+ gc.freeze()
216
+
217
+ with Pool(processes=NUM_WORKERS,
218
+ initializer=init_worker,
219
+ initargs=(known,),
220
+ maxtasksperchild=1000) as pool:
221
+ for hits in pool.imap_unordered(process_batch, batch_generator(), chunksize=1):
222
+ done += BATCH_SIZE
223
+ for phrase, key_hex, addr in hits:
224
+ print(f"\nβœ… MATCH: {phrase}\n priv: {key_hex}\n addr: {addr}\n")
225
+ matches.append((phrase, key_hex, addr))
226
+ with open(MATCHED_FILE, "a", encoding="utf-8") as f:
227
+ f.write(f"{phrase} | {key_hex} | {addr}\n")
228
+
229
+ now = time.time()
230
+ if now - last_log >= 2:
231
+ elapsed = now - start
232
+ rate = done / elapsed if elapsed else 0
233
+ eta = (total - done) / rate if rate else 0
234
+ print(f" ...{done:,}/{total:,} ({100*done/total:.2f}%) ETA {eta/60:.1f}min")
235
+ last_log = now
236
+
237
+ elapsed = time.time() - start
238
+ print(f"\nDone {elapsed:.1f}s. {len(matches)} match(es).")
239
+
240
+ if __name__ == "__main__":
241
+ main()