DILSHAD737 commited on
Commit
5786039
Β·
1 Parent(s): 7af2087

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +300 -0
app.py ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import warnings
3
+ warnings.filterwarnings("ignore", category=UserWarning)
4
+ warnings.filterwarnings("ignore", category=RuntimeWarning)
5
+
6
+ try:
7
+ asyncio.set_event_loop(asyncio.new_event_loop())
8
+ except Exception:
9
+ pass
10
+
11
+ import gradio as gr
12
+ import hashlib, hmac, os, time, math, random, gc
13
+ from itertools import permutations, combinations
14
+ from mnemonic import Mnemonic
15
+ import coincurve
16
+ from eth_utils import keccak, to_checksum_address
17
+ import spaces
18
+
19
+ @spaces.GPU
20
+ def _noop():
21
+ return "ok"
22
+
23
+ # ============================================================
24
+ _MNEMONIC = None
25
+ def _get_mnemonic():
26
+ global _MNEMONIC
27
+ if _MNEMONIC is None:
28
+ _MNEMONIC = Mnemonic("english")
29
+ return _MNEMONIC
30
+
31
+ # ---------- BIP32 manual ----------
32
+ _SECP256K1_N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
33
+ _HARDENED = 0x80000000
34
+
35
+ def _bip32_derive_child_priv(parent_priv, parent_chain, index):
36
+ if index >= _HARDENED:
37
+ data = b'\x00' + parent_priv + index.to_bytes(4, 'big')
38
+ else:
39
+ pub = coincurve.PrivateKey(parent_priv).public_key.format(compressed=True)
40
+ data = pub + index.to_bytes(4, 'big')
41
+ I = hmac.new(parent_chain, data, hashlib.sha512).digest()
42
+ child_int = (int.from_bytes(I[:32], 'big') + int.from_bytes(parent_priv, 'big')) % _SECP256K1_N
43
+ if child_int == 0:
44
+ raise ValueError("Invalid child key")
45
+ return child_int.to_bytes(32, 'big'), I[32:]
46
+
47
+ def seed_to_privkey_hd(seed, address_index=0):
48
+ I = hmac.new(b"Bitcoin seed", seed, hashlib.sha512).digest()
49
+ key, chain = I[:32], I[32:]
50
+ for idx in [44 + _HARDENED, 60 + _HARDENED, _HARDENED, 0, address_index]:
51
+ key, chain = _bip32_derive_child_priv(key, chain, idx)
52
+ return key
53
+
54
+ # ---------- BIP39 ----------
55
+ try:
56
+ import bip39 as _bip39_rust
57
+ _USE_RUST_BIP39 = True
58
+ if hasattr(_bip39_rust, 'phrase_to_seed'):
59
+ _seed_fn = _bip39_rust.phrase_to_seed
60
+ _check_fn = getattr(_bip39_rust, 'check_phrase', None)
61
+ elif hasattr(_bip39_rust, 'bip39_to_seed'):
62
+ _seed_fn = _bip39_rust.bip39_to_seed
63
+ _check_fn = getattr(_bip39_rust, 'bip39_validate', None)
64
+ else:
65
+ _seed_fn = None; _check_fn = None; _USE_RUST_BIP39 = False
66
+ except ImportError:
67
+ _bip39_rust = None; _USE_RUST_BIP39 = False; _seed_fn = None; _check_fn = None
68
+
69
+ def is_valid_bip39(phrase):
70
+ if _USE_RUST_BIP39 and _check_fn:
71
+ return _check_fn(phrase)
72
+ return _get_mnemonic().check(phrase)
73
+
74
+ def phrase_to_seed(phrase, passphrase=""):
75
+ if _USE_RUST_BIP39 and _seed_fn:
76
+ return _seed_fn(phrase, passphrase)
77
+ return _get_mnemonic().to_seed(phrase, passphrase=passphrase)
78
+
79
+ # ---------- Address Cache ----------
80
+ _ADDRESS_CACHE = {}
81
+
82
+ def load_addresses_cached(path):
83
+ if path in _ADDRESS_CACHE:
84
+ cached_mtime, cached_set = _ADDRESS_CACHE[path]
85
+ try:
86
+ current_mtime = os.path.getmtime(path)
87
+ if current_mtime == cached_mtime:
88
+ return cached_set
89
+ except OSError:
90
+ pass
91
+
92
+ s = set()
93
+ with open(path, "r", encoding="utf-8") as f:
94
+ for line in f:
95
+ a = line.strip().strip('"').strip("'").lstrip("\ufeff").lower()
96
+ if a.startswith("0x"):
97
+ a = a[2:]
98
+ if a and len(a) == 40:
99
+ s.add(a)
100
+
101
+ try:
102
+ mtime = os.path.getmtime(path)
103
+ except OSError:
104
+ mtime = 0
105
+ _ADDRESS_CACHE[path] = (mtime, s)
106
+ return s
107
+
108
+ def normalize(addr):
109
+ a = addr.strip().lower()
110
+ if a.startswith("0x"):
111
+ a = a[2:]
112
+ return a
113
+
114
+ # ---------- Generator ----------
115
+ def generate_phrases_for_words(wordlist, mode):
116
+ n = len(wordlist)
117
+ if mode == "order":
118
+ for perm in permutations(wordlist):
119
+ yield " ".join(perm)
120
+ elif mode == "replace":
121
+ for i in range(n):
122
+ for w in wordlist:
123
+ new = wordlist.copy()
124
+ new[i] = w
125
+ yield " ".join(new)
126
+ elif mode == "subset":
127
+ for r in range(1, n + 1):
128
+ for combo in combinations(wordlist, r):
129
+ yield " ".join(combo)
130
+
131
+ # ============================================================
132
+ # Gradio functions
133
+ # ============================================================
134
+
135
+ def generate_random_phrase():
136
+ return _get_mnemonic().generate(strength=128)
137
+
138
+
139
+ def run_multi_phrase_scan(num_phrases, addresses_file, phrase_mode,
140
+ start_index, end_index, passphrase):
141
+ """
142
+ User se poocha gaya number of phrases generate karta hai,
143
+ phir ek ek karke scan karta hai.
144
+ """
145
+ if not os.path.exists(addresses_file):
146
+ return f"❌ File nahi mili: {addresses_file}", ""
147
+
148
+ num_phrases = int(num_phrases)
149
+ if num_phrases < 1:
150
+ return "❌ Kam az kam 1 phrase chahiye", ""
151
+
152
+ start_index = int(start_index)
153
+ end_index = int(end_index)
154
+ if start_index > end_index:
155
+ return "❌ Start index end index se bada nahi ho sakta", ""
156
+
157
+ try:
158
+ known = load_addresses_cached(addresses_file)
159
+ except Exception as e:
160
+ return f"❌ Addresses load fail: {e}", ""
161
+
162
+ if not known:
163
+ return "❌ Koi valid address file mein nahi mila", ""
164
+
165
+ # Generate phrases
166
+ mnemo = _get_mnemonic()
167
+ phrases = [mnemo.generate(strength=128) for _ in range(num_phrases)]
168
+
169
+ log_lines = [
170
+ f"βœ… Loaded {len(known):,} addresses (cached)",
171
+ f"πŸ”§ Mode: {phrase_mode}",
172
+ f"πŸ”‘ Index range: {start_index}–{end_index}",
173
+ f"πŸ“ Phrases to check: {num_phrases}",
174
+ "",
175
+ "Generated phrases:",
176
+ ]
177
+ for i, p in enumerate(phrases, 1):
178
+ log_lines.append(f" {i}. {p}")
179
+ log_lines.append("")
180
+
181
+ matches = []
182
+ start = time.time()
183
+
184
+ for p_idx, phrase in enumerate(phrases, 1):
185
+ log_lines.append(f"πŸ” [{p_idx}/{num_phrases}] Checking: {phrase}")
186
+ words = phrase.strip().split()
187
+ if len(words) != 12:
188
+ log_lines.append(f" ⚠️ Skipped (not 12 words)")
189
+ continue
190
+
191
+ for idx in range(start_index, end_index + 1):
192
+ for phrase_str in generate_phrases_for_words(words, phrase_mode):
193
+ if not is_valid_bip39(phrase_str):
194
+ continue
195
+ try:
196
+ seed = phrase_to_seed(phrase_str, passphrase)
197
+ priv = seed_to_privkey_hd(seed, idx)
198
+ pub = coincurve.PrivateKey(priv).public_key.format(compressed=False)[1:]
199
+ addr = to_checksum_address(keccak(pub)[-20:])
200
+ except Exception:
201
+ continue
202
+ if normalize(addr) in known:
203
+ match_line = (
204
+ f"πŸŽ‰ MATCH!\n"
205
+ f"Phrase: {phrase_str}\n"
206
+ f"Index: {idx}\n"
207
+ f"Key: {priv.hex()}\n"
208
+ f"Addr: {addr}\n"
209
+ )
210
+ log_lines.append(match_line)
211
+ matches.append((phrase_str, idx, priv.hex(), addr))
212
+
213
+ elapsed = time.time() - start
214
+ log_lines.append(f"=== DONE ===")
215
+ log_lines.append(f"Total time: {elapsed:.1f}s")
216
+ log_lines.append(f"Total matches: {len(matches)}")
217
+
218
+ matches_text = "\n".join(
219
+ f"Phrase: {p}\nIndex: {i}\nKey: {k}\nAddr: {a}\n" for p, i, k, a in matches
220
+ ) if matches else "Koi match nahi mila"
221
+
222
+ return "\n".join(log_lines), matches_text
223
+
224
+
225
+ # ============================================================
226
+ # Build UI
227
+ # ============================================================
228
+ with gr.Blocks(title="Phrase Scanner") as demo:
229
+ gr.Markdown("# πŸ” Phrase Scanner")
230
+ gr.Markdown("Kitni random phrases check karni hain? Phir index range ke saath scan karein.")
231
+
232
+ with gr.Row():
233
+ with gr.Column(scale=1):
234
+ gr.Markdown("### Settings")
235
+ num_phrases = gr.Number(
236
+ label="Kitni Random Phrases Check Karein?",
237
+ value=10, precision=0, minimum=1,
238
+ )
239
+ addresses_file = gr.Textbox(
240
+ label="Addresses File",
241
+ value="12730802_addresses.csv",
242
+ )
243
+ phrase_mode = gr.Radio(
244
+ choices=["replace", "order", "subset"],
245
+ value="replace",
246
+ label="Phrase Mode",
247
+ )
248
+ with gr.Row():
249
+ start_index = gr.Number(
250
+ label="Start Index",
251
+ value=0, precision=0, minimum=0,
252
+ )
253
+ end_index = gr.Number(
254
+ label="End Index",
255
+ value=20, precision=0, minimum=0,
256
+ )
257
+ passphrase = gr.Textbox(
258
+ label="BIP39 Passphrase (khali chhod dein)",
259
+ value="",
260
+ type="password",
261
+ )
262
+ run_btn = gr.Button("πŸš€ Scan Shuru Karein", variant="primary")
263
+
264
+ with gr.Column(scale=2):
265
+ gr.Markdown("### Output")
266
+ log_output = gr.Textbox(
267
+ label="Scan Log",
268
+ lines=20,
269
+ max_lines=30,
270
+ interactive=False,
271
+ autoscroll=True,
272
+ )
273
+ matches_output = gr.Textbox(
274
+ label="Matches",
275
+ lines=10,
276
+ interactive=False,
277
+ autoscroll=True,
278
+ )
279
+
280
+ run_btn.click(
281
+ fn=run_multi_phrase_scan,
282
+ inputs=[num_phrases, addresses_file, phrase_mode,
283
+ start_index, end_index, passphrase],
284
+ outputs=[log_output, matches_output],
285
+ )
286
+
287
+ # ZeroGPU requirement
288
+ _noop()
289
+
290
+ _original_launch = demo.launch
291
+ def _patched_launch(**kwargs):
292
+ kwargs.setdefault("ssr_mode", False)
293
+ kwargs.setdefault("share", True)
294
+ kwargs.setdefault("server_name", "0.0.0.0")
295
+ kwargs.setdefault("server_port", 7860)
296
+ return _original_launch(**kwargs)
297
+ demo.launch = _patched_launch
298
+
299
+ if __name__ == "__main__":
300
+ demo.launch(theme=gr.themes.Soft())