DILSHAD737 commited on
Commit
a5f2d8b
·
1 Parent(s): 9cd6dad

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -41
app.py CHANGED
@@ -1,45 +1,130 @@
1
- # debug_which.py
 
 
 
 
2
  from mnemonic import Mnemonic
3
  from eth_account import Account
4
- from eth_utils import keccak, to_checksum_address
5
- import coincurve, hmac, hashlib
6
 
7
  Account.enable_unaudited_hdwallet_features()
8
- phrase = "lesson cushion crane affair federal decline limb spend reunion chief cart zebra"
9
- TARGET = "0x3f0482fc3e9132c3d3acb5f588e980d7b3a5af07"
10
-
11
- # --- Manual BIP32 ---
12
- _N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
13
- _H = 0x80000000
14
- def _child(priv, chain, i):
15
- if i >= _H:
16
- data = b'\x00' + priv + i.to_bytes(4, 'big')
17
- else:
18
- pub = coincurve.PrivateKey(priv).public_key.format(compressed=True)
19
- data = pub + i.to_bytes(4, 'big')
20
- I = hmac.new(chain, data, hashlib.sha512).digest()
21
- ki = (int.from_bytes(I[:32], 'big') + int.from_bytes(priv, 'big')) % _N
22
- return ki.to_bytes(32, 'big'), I[32:]
23
-
24
- def seed_to_privkey_hd(seed, idx=0):
25
- I = hmac.new(b"Bitcoin seed", seed, hashlib.sha512).digest()
26
- key, chain = I[:32], I[32:]
27
- for i in [44+_H, 60+_H, _H, 0, idx]:
28
- key, chain = _child(key, chain, i)
29
- return key
30
-
31
- # Test 1: Python mnemonic + manual BIP32
32
- seed_py = Mnemonic("english").to_seed(phrase, "")
33
- priv_py = seed_to_privkey_hd(seed_py, 0)
34
- pub = coincurve.PrivateKey(priv_py).public_key.format(compressed=False)[1:]
35
- addr_manual = to_checksum_address(keccak(pub)[-20:])
36
-
37
- # Test 2: eth_account
38
- acct = Account.from_mnemonic(phrase, account_path="m/44'/60'/0'/0/0")
39
-
40
- print(f"Manual BIP32: {addr_manual}")
41
- print(f"eth_account: {acct.address}")
42
- print(f"Target: {TARGET}")
43
- print(f"Manual == Target: {addr_manual.lower() == TARGET}")
44
- print(f"eth_account == Target: {acct.address.lower() == TARGET}")
45
- print(f"Manual == eth_account: {addr_manual.lower() == acct.address.lower()}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools
2
+ import math
3
+ import time
4
+ import os
5
+ from multiprocessing import Pool
6
  from mnemonic import Mnemonic
7
  from eth_account import Account
 
 
8
 
9
  Account.enable_unaudited_hdwallet_features()
10
+
11
+ # ============================================================
12
+ words = [
13
+ "lesson", "cushion", "crane", "affair", "federal",
14
+ "decline", "limb", "spend", "reunion", "chief", "cart", "zebra"
15
+ ]
16
+
17
+ ADDRESSES_FILE = "12730802_addresses.csv"
18
+ NUM_WORKERS = 48
19
+ BATCH_SIZE = 2000
20
+ CHECKSUM_PREFILTER = True # True = checksum verify (fast filter), False = skip
21
+ # ============================================================
22
+
23
+ _MNEMONIC = None
24
+
25
+ def get_mnemonic():
26
+ global _MNEMONIC
27
+ if _MNEMONIC is None:
28
+ _MNEMONIC = Mnemonic("english")
29
+ return _MNEMONIC
30
+
31
+
32
+ def load_addresses(path):
33
+ """Lowercase, 0x ke baghair, 40-char addresses ka set."""
34
+ s = set()
35
+ with open(path, "r", encoding="utf-8") as f:
36
+ for line in f:
37
+ a = line.strip().strip('"').strip("'").lstrip("\ufeff").lower()
38
+ if a.startswith("0x"):
39
+ a = a[2:]
40
+ if a and len(a) == 40:
41
+ s.add(a)
42
+ return frozenset(s)
43
+
44
+
45
+ def normalize(addr):
46
+ a = addr.strip().lower()
47
+ if a.startswith("0x"):
48
+ a = a[2:]
49
+ return a
50
+
51
+
52
+ _KNOWN = None
53
+
54
+ def init_worker(known):
55
+ global _KNOWN
56
+ _KNOWN = known
57
+ get_mnemonic() # warm-up
58
+
59
+
60
+ def process_batch(batch):
61
+ hits = []
62
+ known = _KNOWN
63
+ mnemo = get_mnemonic()
64
+ for phrase in batch:
65
+ if CHECKSUM_PREFILTER and not mnemo.check(phrase):
66
+ continue
67
+ try:
68
+ acct = Account.from_mnemonic(phrase)
69
+ except Exception:
70
+ continue
71
+ if normalize(acct.address) in known:
72
+ hits.append((phrase, acct.address, acct.key.hex()))
73
+ return hits
74
+
75
+
76
+ def batch_generator():
77
+ batch = []
78
+ for perm in itertools.permutations(words):
79
+ batch.append(" ".join(perm))
80
+ if len(batch) >= BATCH_SIZE:
81
+ yield batch
82
+ batch = []
83
+ if batch:
84
+ yield batch
85
+
86
+
87
+ def main():
88
+ if not os.path.exists(ADDRESSES_FILE):
89
+ raise SystemExit(f"File nahi mili: {ADDRESSES_FILE}")
90
+
91
+ total = math.factorial(len(words)) # 479,001,600
92
+ print(f"\nMode: order (permutations) | Total: {total:,} | Workers: {NUM_WORKERS}")
93
+ print(f"Batch size: {BATCH_SIZE} | Checksum prefilter: {CHECKSUM_PREFILTER}\n")
94
+
95
+ print("Addresses load ho rahe hain...")
96
+ known = load_addresses(ADDRESSES_FILE)
97
+ print(f"Loaded {len(known):,} addresses\n")
98
+
99
+ matches = []
100
+ done = 0
101
+ start = time.time()
102
+ last_log = start
103
+
104
+ with Pool(processes=NUM_WORKERS,
105
+ initializer=init_worker,
106
+ initargs=(known,)) as pool:
107
+ for hits in pool.imap_unordered(process_batch, batch_generator(), chunksize=4):
108
+ done += BATCH_SIZE
109
+ for phrase, addr, key in hits:
110
+ print(f"\n🎉 MATCH FOUND!")
111
+ print(f"Phrase : {phrase}")
112
+ print(f"Address: {addr}")
113
+ print(f"Key : {key}\n")
114
+ matches.append((phrase, addr, key))
115
+
116
+ now = time.time()
117
+ if now - last_log >= 5:
118
+ elapsed = now - start
119
+ rate = done / elapsed if elapsed else 0
120
+ eta = (total - done) / rate if rate else 0
121
+ print(f" ...{done:,}/{total:,} ({100*done/total:.1f}%) "
122
+ f"{rate:,.0f}/s ETA {eta/60:.1f}min")
123
+ last_log = now
124
+
125
+ elapsed = time.time() - start
126
+ print(f"\nDone {elapsed/60:.1f} min. {len(matches)} match(es).")
127
+
128
+
129
+ if __name__ == "__main__":
130
+ main()