Web3.py EIP-1559 交易 Gas 费计算:baseFee 波动与余额预留
EIP-1559 Gas 费结构 EIP-1559 交易有两个关键字段:maxFeePerGas:你愿意支付的最高单价(base fee + priority fee) maxPriorityFeePerGas:给矿工的小费("tip")节点在验证交易时检查: balance >= value + gasLimit × maxFeePerGas实际扣费是: gasUsed × (baseFeePerGas + priorityFeePerGas)其中 baseFeePerGas 由网络自动调整,gasUsed <= gasLimit。 典型实现(web3.py) from web3 import Web3w3 = Web3(Web3.HTTPProvider("https://mainnet-rpc.example.xyz"))def send_max(private_key, dst_address, chain_id): account = w3.eth.account.from_key(private_key) from_address = account.address balance = w3.eth.get_balance(from_address) nonce = w3.eth.get_transaction_count(from_address) # 动态读取 baseFee base_fee = w3.eth.get_block("latest")["baseFeePerGas"] # 用节点推荐的 priority fee,更可靠 priority_fee = w3.eth.max_priority_fee # maxFee 加 buffer,防 baseFee 上涨 max_fee_per_gas = base_fee * 2 + priority_fee # 估算 gas,比写死更安全 gas_limit = w3.eth.estimate_gas({ "from": from_address, "to": dst_address, "value": 1, }) gas_limit = int(gas_limit * 1.2) # 20% buffer fee = gas_limit * max_fee_per_gas # 预留少量 wei 防止因 baseFee 微小波动导致余额不足 reserve = w3.to_wei(0.000001, "ether") amount = balance - fee - reserve if amount <= 0: print(f"余额不足,balance={balance}, fee={fee}") return None tx = { "from": from_address, "to": Web3.to_checksum_address(dst_address), "value": amount, "gas": gas_limit, "maxFeePerGas": max_fee_per_gas, "maxPriorityFeePerGas": priority_fee, "nonce": nonce, "chainId": chain_id, "type": 2, } signed = w3.eth.account.sign_transaction(tx, private_key) tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction) return tx_hash.hex()常见坑 坑一:maxFee 太紧,baseFee 上涨就失败 # 错误写法:maxFee 刚好等于 baseFee + priority max_fee = base_fee + priority_fee # 一旦下一个区块 baseFee 上涨,交易立即失效改为: max_fee = base_fee * 2 + priority_fee # 留足余量,只多花极少的钱坑二:写死 gasLimit gas_limit = 21000 # ETH 原生转账是这个值,但其他链可能不同更安全的方式: gas_limit = w3.eth.estimate_gas({"from": from_addr, "to": dst, "value": 1}) gas_limit = int(gas_limit * 1.2)坑三:不预留 reserve 导致余额精确到 wei 后失败 节点验证 balance >= value + gasLimit × maxFeePerGas。如果 amount = balance - fee 算完后 baseFee 微涨,条件就不满足。 预留 0.000001 ETH(约 1,000,000,000,000 wei)几乎没有损失但能避免大量边缘失败。 坑四:priority_fee 写死 priority_fee = w3.to_wei(0.1, "gwei") # 可能太低导致交易迟迟不确认改为从节点获取推荐值: priority_fee = w3.eth.max_priority_fee # 节点返回当前合理的 tip
读取 CPU 型号信息:Windows 注册表与 Linux /proc/cpuinfo 方法汇总
CPU 型号信息(如 12th Gen Intel(R) Core(TM) i5-12400)的唯一真实来源是 CPUID 指令,操作系统在启动时读取 CPUID 并将结果缓存到系统结构中,之后所有查询都从这份缓存中读取。 Windows:注册表路径 CPU 信息存放在: HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0关键字段:键名 示例值ProcessorNameString 12th Gen Intel(R) Core(TM) i5-12400VendorIdentifier GenuineIntel~MHz 2500命令行查询: reg query "HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0"wmic 查询(更简洁): wmic cpu get name导出整个 CentralProcessor 分支: reg export "HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor" cpu.regregedit 图形界面: 导航到上述路径 → 右键 → 导出。 Python 读取注册表 import winregkey_path = r"HARDWARE\DESCRIPTION\System\CentralProcessor\0" key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path)cpu_name, _ = winreg.QueryValueEx(key, "ProcessorNameString") vendor, _ = winreg.QueryValueEx(key, "VendorIdentifier") mhz, _ = winreg.QueryValueEx(key, "~MHz")print(cpu_name) # 12th Gen Intel(R) Core(TM) i5-12400Linux:/proc/cpuinfo cat /proc/cpuinfo | grep "model name" | head -1 # model name : 12th Gen Intel(R) Core(TM) i5-12400lscpu | grep "Model name" # Model name: 12th Gen Intel(R) Core(TM) i5-12400/proc/cpuinfo 是内核动态生成的虚拟文件,每次读取都从内核的 cpu_info 结构体生成,本质是 CPUID 的解析结果。 Python 读取: with open('/proc/cpuinfo') as f: for line in f: if line.startswith('model name'): print(line.split(':')[1].strip()) break注意:注册表信息可以被伪装 注册表里的 CPU 信息不是"唯一可信来源":虚拟机(VMware/VirtualBox/Hyper-V)可以在配置中修改 CPUID 返回值 驱动层可以拦截并修改 WMI 查询结果因此注册表/WMI 读取的 CPU 型号可能与物理 CPU 不一致,这是虚拟化平台的常见行为。 各方法对比方法 平台 特点wmic cpu get name Windows 最简单reg query Windows 可脚本化winreg (Python) Windows 程序读取lscpu Linux 格式化输出/proc/cpuinfo Linux 原始详情
BIP39 助记词生成 Solana 地址:SLIP-10 + Ed25519 全流程
BIP39 助记词生成 ETH 地址靠 secp256k1 + keccak256,走 Solana 就完全换了一套——Ed25519 + SLIP-0010,最后不做 hash,直接 Base58 编码公钥。 全流程 助记词 (Mnemonic) │ PBKDF2-HMAC-SHA512 ▼ Seed (64 字节) │ SLIP-0010 (Ed25519) ▼ Master Key │ 按路径 m/44'/501'/0'/0' 派生 ▼ Ed25519 私钥 (32 字节) │ Ed25519 公钥算法 ▼ 公钥 (32 字节) │ Base58 编码 ▼ Solana 地址和 BTC/ETH 唯一相同的只有第一步"助记词转 seed",之后全变了。 第一步:助记词 → seed 标准 BIP39,PBKDF2-HMAC-SHA512: password = 助记词字符串 salt = "mnemonic" + passphrase iters = 2048 output = 64 字节Python: from mnemonic import Mnemonicmnemo = Mnemonic("english") seed = mnemo.to_seed( "abandon abandon abandon abandon abandon abandon " "abandon abandon abandon abandon abandon about", passphrase="", ) print(seed.hex())第二步:seed → Master Key(SLIP-10 Ed25519) Solana 用 SLIP-0010(Ed25519 版本),和 BIP32 的 secp256k1 分道扬镳: I = HMAC-SHA512(key="ed25519 seed", data=seed) IL = master private key (32 字节) IR = master chain code (32 字节)第三步:派生路径 Solana 默认路径: m/44'/501'/0'/0'44':BIP44 501':Solana 的 coin type 0':account 0':change每一级都是 hardened derivation(' 表示 + 2³¹)。Ed25519 只支持 hardened 派生,非 hardened 会直接报错。 第四步:公钥 & 地址 私钥经 Ed25519 算出 32 字节公钥。地址 = Base58(公钥),就这么简单:没有 SHA-256 double hash 没有 RIPEMD-160 没有 keccak 没有 checksum(Base58 本身没自带校验,也没有像 BTC 那样附 4 字节 hash)Python 一把梭 bip_utils 把上面所有细节封好了: from bip_utils import Bip39SeedGenerator, Bip44, Bip44Coinsmnemonic = ("abandon abandon abandon abandon abandon abandon " "abandon abandon abandon abandon abandon about")seed = Bip39SeedGenerator(mnemonic).Generate()bip44 = Bip44.FromSeed(seed, Bip44Coins.SOLANA) account = bip44.Purpose().Coin().Account(0).Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)print("地址:", account.PublicKey().ToAddress()) print("私钥:", account.PrivateKey().Raw().ToHex())Phantom / Solflare 里的第一个账号导出出来应该跟上面一样。 常见误区 Solana 地址和 ETH 地址长得像 其实完全不同:ETH 地址:40 字符 hex + 0x 前缀,checksum 在 EIP-55 里靠大小写实现 Solana 地址:Base58 编码的 32 字节公钥,长度 32~44 字符,无固定前缀Solana 私钥文件是 64 字节而不是 32 Solana 的钱包 JSON(Phantom 导出)通常是 64 字节:前 32 是私钥 seed、后 32 是公钥。生成时: priv32 = account.PrivateKey().Raw().ToBytes() pub32 = account.PublicKey().RawUncompressed().ToBytes()[-32:] keypair_bytes = priv32 + pub32 # 64 字节导入 solana-cli 或 Phantom 时用这个格式。 Ed25519 派生路径可以省略部分层级 Phantom 早期用 m/44'/501'/0'(只三层)而非 m/44'/501'/0'/0'——同一助记词在这两种路径下算出来的地址不同。发现"钱包地址对不上"时先检查是不是路径差异,试试:m/44'/501'/0' — Phantom "legacy" m/44'/501'/0'/0' — 现在的默认一句话总结 Solana 地址生成 = BIP39 seed → SLIP-10 Ed25519 派生 → Base58(公钥)。和 EVM 完全两套加密路径,别拿 ETH 的经验类比。用 bip_utils 三行搞定,别自己实现 Ed25519。
GPU 租赁平台架构:Agent 节点管理、Docker 容器调度与供给冷启动
核心难点:供给而非技术 GPU 租赁平台最先需要解决的问题不是如何调度,而是为什么别人愿意把 GPU 挂到你的平台。供方需要确认:平台真的有租用需求,不会长期空跑 收益能覆盖电费和硬件损耗 提现流程可靠 机器不会被用于挖矿或违法用途Agent 节点管理(主流方案) Agent 是一个安装在供方机器上的后台进程,负责: 采集信息 ├── GPU 型号 / 显存 / 温度 ├── CPU 利用率 ├── 内存 / 硬盘 ├── 公网 IP / 带宽 ├── 在线状态 └── CUDA 版本 / 驱动版本上报到平台服务器 ↓ 控制台展示节点列表 ↓ 用户下单 → Agent 收到任务 → 启动容器Agent 还需要支持:开机自启、掉线重连、心跳保活、远程执行命令。 容器调度(Docker Worker) 大多数 GPU Marketplace 用 Docker 而非虚拟机: # 接单后自动执行 docker pull nvidia/cuda:12.0-base docker run \ --gpus all \ -p 30000:22 \ -d nvidia/cuda:12.0-base sleep infinity# 租户通过 SSH 接入 ssh user@node-ip -p 30000也可以直接暴露 Jupyter 或 ComfyUI 等界面,省去 SSH 配置。 Docker vs 虚拟机方案 优点 缺点Docker 启动快、开销小 隔离性略弱KVM/QEMU 安全隔离好 GPU 透传(PCI passthrough)配置复杂生产环境主流选 Docker,只有对安全隔离有严格要求的场景才考虑虚拟机。 闲置 GPU 共享(家用机) Agent 可以实现智能避让: def should_accept_task(): gpu_util = get_gpu_utilization() # nvidia-smi cpu_util = get_cpu_utilization() user_active = is_user_active() # 检测鼠标 / 键盘活动 return gpu_util < 10 and cpu_util < 10 and not user_active用户回来玩游戏时 Agent 自动暂停任务、释放 GPU。 计费与分润 用户支付租金 ↓ 平台抽成(通常 10~30%) ↓ 供方获得剩余收益平台抽成比例需要在"吸引供方"和"平台可持续"之间平衡。 冷启动策略 新平台面临先有鸡还是先有蛋的问题,推荐分阶段:先签稳定供方:找渲染农场、AI 创业团队、网吧(高配置机器)合作,保证第一批节点稳定在线 建控制台:展示节点状态、GPU 利用率、收益统计 实现任务调度:支持自动分配节点、启动 Docker 容器 最后开放市场:加入公开租用、计费、支付、评分系统每个阶段独立验证价值,避免同时解决供给、需求、调度、支付四个难题。
给工具起名和写简历项目:从 "XX 助手" 升级
给自己做的工具起名 / 写简历里的项目描述,都有个共通的坑——词汇太朴素。"XX 助手"、"XX 工具"、"XX 平台"这类词一看就是学生项目。稍微换个词就能显得专业得多。 工具起名的思路 高级感的名字通常从这几类词里选: 观察 / 监控类:Monitor、Observer、Sentinel、Watcher、Guardian、Radar、Scope、Insight、Vision 智能 / 分析类:Intelligence、Analytics、Nexus、Matrix、Engine、Pulse、Beacon、Prism 天文 / 神话(黑科技风):HawkEye、Falcon、Orion、Nebula、Polaris、Helios、Atlas、Nova、Phantom SaaS 风(推荐):FanScope、FanPulse、FanInsight、FollowRadar、DataScope 之类的"XXScope / XXInsight / XXPulse"。 举个例子 一个"微博粉丝监控"工具怎么起名: 朴素版:微博粉丝监控助手 / 微博粉丝监控工具 升级版:FanScope — 简洁、有辨识度、能扩展到 X/Instagram/TikTok FanInsight — 强调"洞察" Weibo Sentinel(微博哨兵) — 更符合中文语境 Weibo Radar(微博雷达) — 类似 GitHub Radar Follower Intelligence — B 端 SaaS 感加副标题:FanScope · 社交粉丝监测中心 起名的实用原则短:1-3 个词、8 个字母以内更好 可扩展:别把范围写死("微博"XX 后面就扩不到 X) 可拼:能一次听清楚(客户口头传播) 域名可注册:.io / .ai / .app 或者不常见的 .dev 英文:面向国际市场就英文;纯国内也可以中文(微博哨兵) 有辨识度:避免和知名产品撞名简历里的项目描述 同一个坑。见过这种: 项目:微博粉丝监控助手 技术:动态代理池、过滑块验证码、请求重试面试官看完只知道你"做了个爬虫",不知道你的价值。 三步升级 第一步:把功能点包装成技术能力 不要写"过滑块验证码",写"构建智能验证码识别与自动化验证模块"。 第二步:加上"解决了什么问题" "设计请求风控对抗策略,提高数据采集稳定性与成功率"。 第三步:能量化就量化"代理可用率保持 95%+" "任务稳定运行 7×24 小时" "单机采集速度提升 3 倍,日均处理 100 万+ 请求"完整模板 ## FanScope · 社交粉丝监测中心技术栈:Python 3.11、FastAPI、Playwright、Redis、PostgreSQL、Celery**项目亮点**:- 设计并实现高可用代理资源管理系统,支持动态扩容、健康检测及智能调度 → 代理可用率保持 95%+,降低采集失败率 60%+ - 构建自动化验证处理能力,提升复杂交互场景下的任务成功率 → 验证成功率提升至 90%+ - 实现多维度风控规避策略(请求节流、指纹管理、访问策略优化) → 任务稳定运行 7×24 小时 - 搭建可观测监控体系,支持日志分析、异常告警及性能统计比原始描述专业得多。 数据量化的技巧 没有精确数据怎么办?给一个合理区间,别虚构离谱数字。"支持 千级并发"——比"支持很多并发"具体 "响应延迟 < 100ms"——具体指标 "服务 10 万+ 用户"——有量级 "覆盖 80% 主流场景"——覆盖率面试官问细节时能说清是怎么算的就行,不用给具体日志。 常见项目类型的表达原始描述 升级后做了个爬虫 自研分布式数据采集系统过滑块验证码 构建自动化验证识别与处理模块动态代理池 高可用代理资源管理与智能调度增加了缓存 引入分级缓存策略,接口 P99 从 500ms 降至 80ms做了后台管理 搭建面向 XX 场景的管理平台,支持多角色权限用 WebSocket 推消息 设计双向长连接推送协议,支持多端订阅写了小程序 独立完成 XX 小程序前端,覆盖 XX 核心业务我的建议 写项目描述时,脑子里过一遍这三个问题:这个项目解决了什么问题?(不是"实现了什么",是"为什么要做") 技术选型的理由是什么?(面试常问) 可量化的成果是什么?(可能是性能、可用性、覆盖率、用户量)三个问题都想清楚,简历里那两行字自然就出得来。 一句话总结 工具起名用 Sentinel / Insight / Radar / Pulse / Scope 这类词升级"XX 助手"。简历项目用 "技术能力 + 解决什么 + 量化成果" 三段式,比堆技术栈有说服力。
