DILSHAD737 commited on
Commit
516940f
·
1 Parent(s): 7539ffc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +179 -5
app.py CHANGED
@@ -5,9 +5,6 @@ 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
-
11
  # ============================================================
12
  words = [
13
  "lesson", "cushion", "crane", "affair", "federal",
@@ -19,11 +16,188 @@ USE_BIP39 = True
19
  BIP39_PASSPHRASE = ""
20
  HD_DERIVATION = True
21
  ADDRESS_INDEX = 0
22
- CHECK_BIP39_CHECKSUM = False # ✅ FIX: prefilter band
23
  ADDRESSES_FILE = "12730802_addresses.csv"
24
  MATCHED_FILE = f"matched_keys_{PHRASE_MODE}.txt"
25
  BATCH_SIZE = 500
26
  NUM_WORKERS = 96
27
  # ============================================================
28
 
29
- # ... (baaki code same rahega, sirf debug prints hata dein)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import coincurve
6
  from eth_utils import keccak, to_checksum_address
7
 
 
 
 
8
  # ============================================================
9
  words = [
10
  "lesson", "cushion", "crane", "affair", "federal",
 
16
  BIP39_PASSPHRASE = ""
17
  HD_DERIVATION = True
18
  ADDRESS_INDEX = 0
19
+ CHECK_BIP39_CHECKSUM = False # ✅ prefilter band
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
+
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
+ # Sirf tab use hoga jab CHECK_BIP39_CHECKSUM = True ho
69
+ return _get_mnemonic().check(phrase)
70
+
71
+ def phrase_to_seed(phrase):
72
+ if _USE_RUST_BIP39:
73
+ return _bip39_rust.bip39_mnemonic_to_seed(phrase, BIP39_PASSPHRASE)
74
+ return _get_mnemonic().to_seed(phrase, passphrase=BIP39_PASSPHRASE)
75
+
76
+ # ---------- Address file ----------
77
+ def load_addresses(path):
78
+ s = set()
79
+ with open(path, "r", encoding="utf-8") as f:
80
+ for line in f:
81
+ a = line.strip().strip('"').strip("'").lstrip("\ufeff").lower()
82
+ if a.startswith("0x"):
83
+ a = a[2:]
84
+ if a and len(a) == 40:
85
+ s.add(a)
86
+ return frozenset(s)
87
+
88
+ def normalize(addr):
89
+ a = addr.strip().lower()
90
+ if a.startswith("0x"):
91
+ a = a[2:]
92
+ return a
93
+
94
+ # ---------- Generator ----------
95
+ def generate_phrases():
96
+ n = len(words)
97
+ if PHRASE_MODE == "order":
98
+ for perm in permutations(words):
99
+ yield " ".join(perm)
100
+ elif PHRASE_MODE == "replace":
101
+ for i in range(n):
102
+ for w in words:
103
+ new = words.copy()
104
+ new[i] = w
105
+ yield " ".join(new)
106
+ elif PHRASE_MODE == "subset":
107
+ for r in range(1, n + 1):
108
+ for combo in combinations(words, r):
109
+ yield " ".join(combo)
110
+
111
+ def count_total():
112
+ n = len(words)
113
+ if PHRASE_MODE == "order": return math.factorial(n)
114
+ if PHRASE_MODE == "replace": return n * n
115
+ if PHRASE_MODE == "subset": return 2**n - 1
116
+
117
+ # ---------- Worker ----------
118
+ _KNOWN = None
119
+
120
+ def init_worker(known):
121
+ global _KNOWN
122
+ _KNOWN = known
123
+ _get_mnemonic()
124
+
125
+ def process_batch(batch):
126
+ hits = []
127
+ known = _KNOWN
128
+ for phrase in batch:
129
+ if CHECK_BIP39_CHECKSUM and not is_valid_bip39_fast(phrase):
130
+ continue
131
+ try:
132
+ seed = phrase_to_seed(phrase)
133
+ if HD_DERIVATION:
134
+ priv = seed_to_privkey_hd(seed, ADDRESS_INDEX)
135
+ else:
136
+ priv = seed[:32]
137
+ pub = coincurve.PrivateKey(priv).public_key.format(compressed=False)[1:]
138
+ addr = to_checksum_address(keccak(pub)[-20:])
139
+ except Exception:
140
+ continue
141
+ if normalize(addr) 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
+ if os.path.exists(MATCHED_FILE):
174
+ os.remove(MATCHED_FILE)
175
+
176
+ gc.collect()
177
+ gc.freeze()
178
+
179
+ with Pool(processes=NUM_WORKERS,
180
+ initializer=init_worker,
181
+ initargs=(known,),
182
+ maxtasksperchild=1000) as pool:
183
+ for hits in pool.imap_unordered(process_batch, batch_generator(), chunksize=1):
184
+ done += BATCH_SIZE
185
+ for phrase, key_hex, addr in hits:
186
+ print(f"\n✅ MATCH: {phrase}\n priv: {key_hex}\n addr: {addr}\n")
187
+ matches.append((phrase, key_hex, addr))
188
+ with open(MATCHED_FILE, "a", encoding="utf-8") as f:
189
+ f.write(f"{phrase} | {key_hex} | {addr}\n")
190
+
191
+ now = time.time()
192
+ if now - last_log >= 2:
193
+ elapsed = now - start
194
+ rate = done / elapsed if elapsed else 0
195
+ eta = (total - done) / rate if rate else 0
196
+ print(f" ...{done:,}/{total:,} ({100*done/total:.1f}%) ETA {eta:.0f}s")
197
+ last_log = now
198
+
199
+ elapsed = time.time() - start
200
+ print(f"\nDone {elapsed:.1f}s. {len(matches)} match(es).")
201
+
202
+ if __name__ == "__main__":
203
+ main()