DILSHAD737 commited on
Commit
1f58917
·
1 Parent(s): e415917

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +176 -45
app.py CHANGED
@@ -1,15 +1,29 @@
1
- # debug_replace.py
2
- from itertools import permutations
3
- import hashlib, hmac
4
  from eth_account import Account
5
- from mnemonic import Mnemonic
6
- from eth_utils import keccak, to_checksum_address
7
  import coincurve
 
8
 
9
- words = ["lesson", "cushion", "crane", "affair", "federal", "decline", "limb", "spend", "reunion", "chief", "cart", "zebra"]
10
- TARGET = "0x3f0482fc3e9132c3d3acb5f588e980d7b3a5af07"
 
 
 
11
 
12
- # BIP32 helpers (aapke code se copy)
 
 
 
 
 
 
 
 
 
 
 
 
13
  _SECP256K1_N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
14
  _HARDENED = 0x80000000
15
 
@@ -21,6 +35,8 @@ def _bip32_derive_child_priv(parent_priv, parent_chain, index):
21
  data = pub + index.to_bytes(4, 'big')
22
  I = hmac.new(parent_chain, data, hashlib.sha512).digest()
23
  child_int = (int.from_bytes(I[:32], 'big') + int.from_bytes(parent_priv, 'big')) % _SECP256K1_N
 
 
24
  return child_int.to_bytes(32, 'big'), I[32:]
25
 
26
  def seed_to_privkey_hd(seed, address_index=0):
@@ -31,40 +47,155 @@ def seed_to_privkey_hd(seed, address_index=0):
31
  key, chain = _bip32_derive_child_priv(key, chain, idx)
32
  return key
33
 
34
- # Generate first 5 replace phrases
35
- n = len(words)
36
- count = 0
37
- for i in range(n):
38
- for w in words:
39
- new = words.copy()
40
- new[i] = w
41
- phrase = " ".join(new)
42
- count += 1
43
-
44
- # Derive address
45
- seed = Mnemonic("english").to_seed(phrase, passphrase="")
46
- priv = seed_to_privkey_hd(seed, 0)
47
- pub = coincurve.PrivateKey(priv).public_key.format(compressed=False)[1:]
48
- addr = to_checksum_address(keccak(pub)[-20:])
49
- addr_lower = addr.lower()
50
-
51
- match = "✅ MATCH" if addr_lower == TARGET.lower() else ""
52
- print(f"{count:3d}. {phrase}")
53
- print(f" -> {addr} {match}")
54
-
55
- if count >= 5:
56
- break
57
- if count >= 5:
58
- break
59
-
60
- # Also check the exact target phrase
61
- print("\n--- Exact target phrase ---")
62
- phrase = "lesson cushion crane affair federal decline limb spend reunion chief cart zebra"
63
- seed = Mnemonic("english").to_seed(phrase, passphrase="")
64
- priv = seed_to_privkey_hd(seed, 0)
65
- pub = coincurve.PrivateKey(priv).public_key.format(compressed=False)[1:]
66
- addr = to_checksum_address(keccak(pub)[-20:])
67
- print(f"Phrase: {phrase}")
68
- print(f"Addr: {addr}")
69
- print(f"Target: {TARGET}")
70
- print(f"Match: {addr.lower() == TARGET.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 = False
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
+ # ---------- BIP32 (same as before) ----------
27
  _SECP256K1_N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
28
  _HARDENED = 0x80000000
29
 
 
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):
 
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.lower()
135
+ priv = acct.key
136
+ except Exception:
137
+ continue
138
+ normalized = normalize(addr)
139
+ if normalized in known:
140
+ hits.append((phrase, priv.hex(), addr))
141
+ return hits
142
+
143
+ def batch_generator():
144
+ batch = []
145
+ for phrase in generate_phrases():
146
+ batch.append(phrase)
147
+ if len(batch) >= BATCH_SIZE:
148
+ yield batch
149
+ batch = []
150
+ if batch:
151
+ yield batch
152
+
153
+ # ---------- Main ----------
154
+ def main():
155
+ if not os.path.exists(ADDRESSES_FILE):
156
+ raise SystemExit(f"File nahi mili: {ADDRESSES_FILE}")
157
+
158
+ total = count_total()
159
+ print(f"\nMode: {PHRASE_MODE} | Total: {total:,} | Workers: {NUM_WORKERS}")
160
+ print(f"HD: {HD_DERIVATION} (index {ADDRESS_INDEX})")
161
+ print(f"Checksum prefilter: {CHECK_BIP39_CHECKSUM}\n")
162
+
163
+ known = load_addresses(ADDRESSES_FILE)
164
+ print(f"Loaded {len(known):,} addresses\n")
165
+
166
+ matches = []
167
+ done = 0
168
+ start = time.time()
169
+ last_log = start
170
+
171
+ if os.path.exists(MATCHED_FILE):
172
+ os.remove(MATCHED_FILE)
173
+
174
+ gc.collect()
175
+ gc.freeze()
176
+
177
+ with Pool(processes=NUM_WORKERS,
178
+ initializer=init_worker,
179
+ initargs=(known,),
180
+ maxtasksperchild=1000) as pool:
181
+ for hits in pool.imap_unordered(process_batch, batch_generator(), chunksize=1):
182
+ done += BATCH_SIZE
183
+ for phrase, key_hex, addr in hits:
184
+ print(f"\n✅ MATCH: {phrase}\n priv: {key_hex}\n addr: {addr}\n")
185
+ matches.append((phrase, key_hex, addr))
186
+ with open(MATCHED_FILE, "a", encoding="utf-8") as f:
187
+ f.write(f"{phrase} | {key_hex} | {addr}\n")
188
+
189
+ now = time.time()
190
+ if now - last_log >= 2:
191
+ elapsed = now - start
192
+ rate = done / elapsed if elapsed else 0
193
+ eta = (total - done) / rate if rate else 0
194
+ print(f" ...{done:,}/{total:,} ({100*done/total:.1f}%) ETA {eta:.0f}s")
195
+ last_log = now
196
+
197
+ elapsed = time.time() - start
198
+ print(f"\nDone {elapsed:.1f}s. {len(matches)} match(es).")
199
+
200
+ if __name__ == "__main__":
201
+ main()