416 lines
14 KiB
Python
416 lines
14 KiB
Python
"""
|
||
EVM助记词碰撞工具 - 高速版本
|
||
批量生成助记词并检查余额,发现有钱包自动保存
|
||
|
||
依赖安装:
|
||
pip install mnemonic eth-account web3 loguru
|
||
|
||
使用方法:
|
||
python evm_助记词查询余额.py
|
||
"""
|
||
|
||
import os
|
||
import json
|
||
import threading
|
||
from datetime import datetime
|
||
from mnemonic import Mnemonic
|
||
from eth_account import Account
|
||
from web3 import Web3
|
||
from loguru import logger
|
||
import time
|
||
|
||
# 尝试导入POA中间件
|
||
try:
|
||
from web3.middleware import geth_poa_middleware
|
||
except ImportError:
|
||
try:
|
||
from web3.middleware.geth_poa import geth_poa_middleware
|
||
except ImportError:
|
||
geth_poa_middleware = None
|
||
|
||
# 配置日志
|
||
logger.remove()
|
||
logger.add(lambda msg: print(msg, end=''), format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | {message}", level="INFO")
|
||
|
||
# 全局统计
|
||
stats = {
|
||
'total_checked': 0,
|
||
'found_balance': 0,
|
||
'start_time': time.time(),
|
||
'lock': threading.Lock()
|
||
}
|
||
|
||
# 结果保存文件
|
||
RESULTS_FILE = "found_wallets.txt"
|
||
SAVE_LOCK = threading.Lock()
|
||
|
||
|
||
class FastEVMWallet:
|
||
"""高速EVM钱包碰撞工具"""
|
||
|
||
# 优化的RPC端点(使用多个备用节点提高速度)
|
||
RPC_ENDPOINTS = {
|
||
"ethereum": [
|
||
"https://eth.llamarpc.com",
|
||
"https://rpc.ankr.com/eth",
|
||
"https://ethereum.publicnode.com",
|
||
],
|
||
"bsc": [
|
||
"https://bsc-dataseed1.binance.org",
|
||
"https://bsc-dataseed2.binance.org",
|
||
"https://rpc.ankr.com/bsc",
|
||
],
|
||
# "polygon": [
|
||
# "https://polygon-rpc.com",
|
||
# "https://rpc.ankr.com/polygon",
|
||
# ],
|
||
# "arbitrum": [
|
||
# "https://arb1.arbitrum.io/rpc",
|
||
# "https://rpc.ankr.com/arbitrum",
|
||
# ],
|
||
# "optimism": [
|
||
# "https://mainnet.optimism.io",
|
||
# "https://rpc.ankr.com/optimism",
|
||
# ],
|
||
"base": [
|
||
"https://mainnet.base.org",
|
||
"https://rpc.ankr.com/base",
|
||
],
|
||
}
|
||
|
||
def __init__(self, chains=None):
|
||
"""
|
||
初始化
|
||
|
||
Args:
|
||
chains: 要查询的链列表,None表示查询所有链
|
||
"""
|
||
self.mnemo = Mnemonic("english")
|
||
Account.enable_unaudited_hdwallet_features()
|
||
|
||
# 选择要查询的链(默认只查询主要链以提高速度)
|
||
if chains is None:
|
||
self.chains = ["ethereum", "bsc", "polygon", "arbitrum", "base"]
|
||
else:
|
||
self.chains = chains
|
||
|
||
# 为每个链创建Web3连接池
|
||
self.w3_pools = {}
|
||
self._init_connections()
|
||
|
||
def _init_connections(self):
|
||
"""初始化RPC连接"""
|
||
logger.info("正在初始化RPC连接...")
|
||
for chain in self.chains:
|
||
if chain in self.RPC_ENDPOINTS:
|
||
# 尝试所有RPC节点,直到找到一个可用的
|
||
w3 = None
|
||
for rpc_url in self.RPC_ENDPOINTS[chain]:
|
||
try:
|
||
# 设置更短的超时时间,避免阻塞
|
||
w3 = Web3(Web3.HTTPProvider(rpc_url, request_kwargs={'timeout': 3}))
|
||
|
||
# 某些链需要POA中间件
|
||
if chain in ["bsc", "polygon"] and geth_poa_middleware is not None:
|
||
try:
|
||
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
|
||
except:
|
||
pass
|
||
|
||
# 测试连接(快速测试)
|
||
try:
|
||
if w3.is_connected():
|
||
self.w3_pools[chain] = w3
|
||
logger.info(f"✓ {chain} 连接成功: {rpc_url}")
|
||
break
|
||
except:
|
||
continue
|
||
except Exception as e:
|
||
continue
|
||
|
||
if chain not in self.w3_pools:
|
||
logger.warning(f"✗ {chain} 连接失败,将跳过该链")
|
||
|
||
def generate_mnemonic(self, strength=128):
|
||
"""快速生成助记词"""
|
||
return self.mnemo.generate(strength=strength)
|
||
|
||
def mnemonic_to_address(self, mnemonic, account_index=0):
|
||
"""
|
||
从助记词快速生成地址(不生成私钥,节省时间)
|
||
|
||
Returns:
|
||
str: 钱包地址,失败返回None
|
||
"""
|
||
try:
|
||
account = Account.from_mnemonic(mnemonic, account_path=f"m/44'/60'/0'/0/{account_index}")
|
||
return account.address
|
||
except:
|
||
return None
|
||
|
||
def quick_check_balance(self, address):
|
||
"""
|
||
快速检查地址是否有余额(只检查主要链,一旦发现余额就返回)
|
||
|
||
Returns:
|
||
dict: 如果有余额返回余额信息,否则返回None
|
||
"""
|
||
# 只检查最快的链(ethereum和bsc),提高速度
|
||
priority_chains = ["ethereum", "bsc"]
|
||
|
||
for chain in priority_chains:
|
||
if chain not in self.chains:
|
||
continue
|
||
try:
|
||
w3 = self.w3_pools.get(chain)
|
||
if not w3:
|
||
continue
|
||
|
||
# 查询余额(设置超时,避免阻塞)
|
||
try:
|
||
balance_wei = w3.eth.get_balance(address)
|
||
|
||
if balance_wei > 0:
|
||
balance_eth = Web3.from_wei(balance_wei, 'ether')
|
||
return {
|
||
'chain': chain,
|
||
'address': address,
|
||
'balance_wei': balance_wei,
|
||
'balance_eth': float(balance_eth),
|
||
'balance_formatted': f"{balance_eth:.6f} ETH"
|
||
}
|
||
except Exception as e:
|
||
# 查询失败,尝试下一个链
|
||
continue
|
||
except:
|
||
continue
|
||
|
||
return None
|
||
|
||
def check_all_chains(self, address):
|
||
"""
|
||
检查所有链的余额(发现余额后调用)
|
||
|
||
Returns:
|
||
list: 所有有余额的链信息
|
||
"""
|
||
results = []
|
||
for chain in self.chains:
|
||
try:
|
||
w3 = self.w3_pools.get(chain)
|
||
if not w3 or not w3.is_connected():
|
||
continue
|
||
|
||
balance_wei = w3.eth.get_balance(address)
|
||
if balance_wei > 0:
|
||
balance_eth = Web3.from_wei(balance_wei, 'ether')
|
||
results.append({
|
||
'chain': chain,
|
||
'balance_wei': balance_wei,
|
||
'balance_eth': float(balance_eth),
|
||
'balance_formatted': f"{balance_eth:.6f} ETH"
|
||
})
|
||
except:
|
||
continue
|
||
|
||
return results
|
||
|
||
|
||
def save_found_wallet(mnemonic, address, private_key, balances):
|
||
"""保存发现的钱包信息"""
|
||
with SAVE_LOCK:
|
||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||
info = {
|
||
'timestamp': timestamp,
|
||
'mnemonic': mnemonic,
|
||
'address': address,
|
||
'private_key': private_key,
|
||
'balances': balances
|
||
}
|
||
|
||
# 保存到文件
|
||
with open(RESULTS_FILE, 'a', encoding='utf-8') as f:
|
||
f.write("="*80 + "\n")
|
||
f.write(f"发现时间: {timestamp}\n")
|
||
f.write(f"助记词: {mnemonic}\n")
|
||
f.write(f"地址: {address}\n")
|
||
f.write(f"私钥: {private_key}\n")
|
||
f.write("余额信息:\n")
|
||
for balance in balances:
|
||
f.write(f" {balance['chain'].upper()}: {balance['balance_formatted']}\n")
|
||
f.write("="*80 + "\n\n")
|
||
|
||
# 同时保存JSON格式
|
||
json_file = RESULTS_FILE.replace('.txt', '.json')
|
||
try:
|
||
if os.path.exists(json_file):
|
||
with open(json_file, 'r', encoding='utf-8') as f:
|
||
data = json.load(f)
|
||
else:
|
||
data = []
|
||
|
||
data.append(info)
|
||
with open(json_file, 'w', encoding='utf-8') as f:
|
||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||
except:
|
||
pass
|
||
|
||
|
||
def worker_thread(wallet_tool, thread_id):
|
||
"""工作线程:生成助记词并检查余额"""
|
||
global stats
|
||
|
||
# 每个线程独立计数,减少锁竞争
|
||
local_count = 0
|
||
thread_start_time = time.time()
|
||
|
||
while True:
|
||
try:
|
||
# 生成助记词
|
||
mnemonic = wallet_tool.generate_mnemonic()
|
||
|
||
# 生成地址
|
||
address = wallet_tool.mnemonic_to_address(mnemonic)
|
||
if not address:
|
||
local_count += 1
|
||
# 立即更新统计(不等待)
|
||
if local_count >= 1: # 每次都更新,确保统计正常
|
||
with stats['lock']:
|
||
stats['total_checked'] += local_count
|
||
local_count = 0
|
||
continue
|
||
|
||
# 先更新统计(在查询余额之前)
|
||
local_count += 1
|
||
if local_count >= 1: # 每次都更新
|
||
with stats['lock']:
|
||
stats['total_checked'] += local_count
|
||
total = stats['total_checked']
|
||
found = stats['found_balance']
|
||
if total % 20 == 0: # 每20次打印一次
|
||
elapsed = time.time() - stats['start_time']
|
||
speed = total / elapsed if elapsed > 0 else 0
|
||
logger.info(f"已检查: {total} | 发现: {found} | 速度: {speed:.1f} 个/秒")
|
||
local_count = 0
|
||
|
||
# 快速检查余额(只检查主要链,设置超时)
|
||
try:
|
||
balance_info = wallet_tool.quick_check_balance(address)
|
||
except:
|
||
balance_info = None
|
||
|
||
# 如果发现余额
|
||
if balance_info:
|
||
# 生成私钥
|
||
account = Account.from_mnemonic(mnemonic, account_path="m/44'/60'/0'/0/0")
|
||
private_key = account.key.hex()
|
||
|
||
# 检查所有链的余额
|
||
all_balances = wallet_tool.check_all_chains(address)
|
||
|
||
# 保存结果
|
||
save_found_wallet(mnemonic, address, private_key, all_balances)
|
||
|
||
# 更新统计并打印
|
||
with stats['lock']:
|
||
stats['found_balance'] += 1
|
||
|
||
logger.success(f"🎉 发现余额钱包!")
|
||
logger.success(f"地址: {address}")
|
||
logger.success(f"助记词: {mnemonic}")
|
||
for bal in all_balances:
|
||
logger.success(f" {bal['chain'].upper()}: {bal['balance_formatted']}")
|
||
|
||
except Exception as e:
|
||
# 即使出错也更新统计
|
||
local_count += 1
|
||
if local_count >= 1:
|
||
with stats['lock']:
|
||
stats['total_checked'] += local_count
|
||
local_count = 0
|
||
continue
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("="*80)
|
||
print("EVM助记词碰撞工具 - 高速版本")
|
||
print("="*80)
|
||
print(f"结果将保存到: {RESULTS_FILE}")
|
||
print(f"查询的链: ethereum, bsc, polygon, arbitrum, base")
|
||
print("="*80)
|
||
print()
|
||
|
||
# 选择要查询的链(可以修改这里)
|
||
chains = ["ethereum", "bsc", "polygon", "arbitrum", "base"]
|
||
|
||
# 创建钱包工具
|
||
wallet_tool = FastEVMWallet(chains=chains)
|
||
|
||
# 设置线程数(根据CPU核心数调整)
|
||
num_threads = os.cpu_count() or 4
|
||
print(f"启动 {num_threads} 个工作线程...")
|
||
print("按 Ctrl+C 停止程序\n")
|
||
|
||
# 创建线程
|
||
threads = []
|
||
|
||
for i in range(num_threads):
|
||
t = threading.Thread(target=worker_thread, args=(wallet_tool, i), daemon=True)
|
||
t.start()
|
||
threads.append(t)
|
||
|
||
# 等待一小段时间确保线程启动
|
||
time.sleep(1)
|
||
|
||
# 检查是否有线程在运行
|
||
active_threads = sum(1 for t in threads if t.is_alive())
|
||
if active_threads == 0:
|
||
logger.error("所有工作线程都停止了,请检查RPC连接")
|
||
return
|
||
else:
|
||
logger.info(f"✓ {active_threads} 个工作线程正在运行")
|
||
|
||
# 测试:生成一个测试地址并查询,验证功能是否正常
|
||
logger.info("正在测试功能...")
|
||
test_mnemonic = wallet_tool.generate_mnemonic()
|
||
test_address = wallet_tool.mnemonic_to_address(test_mnemonic)
|
||
if test_address:
|
||
logger.info(f"测试地址生成成功: {test_address[:10]}...")
|
||
test_balance = wallet_tool.quick_check_balance(test_address)
|
||
if test_balance is None:
|
||
logger.info("测试余额查询成功(无余额,正常)")
|
||
else:
|
||
logger.warning(f"测试发现余额!这不太可能,请检查")
|
||
else:
|
||
logger.error("测试地址生成失败!")
|
||
|
||
try:
|
||
# 主线程等待
|
||
last_count = 0
|
||
while True:
|
||
time.sleep(2) # 每2秒更新一次显示
|
||
# 定期打印统计信息
|
||
elapsed = time.time() - stats['start_time']
|
||
current_count = stats['total_checked']
|
||
|
||
# 如果计数没有变化,可能是线程有问题
|
||
if elapsed > 10 and current_count == last_count and current_count == 0:
|
||
logger.warning("警告:工作线程可能没有正常工作,请检查RPC连接")
|
||
|
||
if elapsed > 0:
|
||
speed = current_count / elapsed if current_count > 0 else 0
|
||
print(f"\r运行时间: {int(elapsed)}秒 | 已检查: {current_count} | 发现: {stats['found_balance']} | 速度: {speed:.1f} 个/秒", end='', flush=True)
|
||
|
||
last_count = current_count
|
||
except KeyboardInterrupt:
|
||
print("\n\n正在停止...")
|
||
print(f"\n最终统计:")
|
||
print(f" 总检查数: {stats['total_checked']}")
|
||
print(f" 发现余额: {stats['found_balance']}")
|
||
print(f" 结果已保存到: {RESULTS_FILE}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|