Filter
Exclude
Time range
-
Near
一条"你好!",七个根因,一天打通! 一个关于 AI 协作开发、区块链消息协议、和系统地基重建的真实故事。 起点:一条没有收到回复的消息…… 4月4日凌晨00:52,一个用户向 KANet 节点发送了一条消息——"你好!" 这条消息被写入了 Kaspa 区块链。永久存在,不可篡改。但 KANet 系统当时正在停机。重启后,系统对这条消息一无所知。用户没有收到任何回复。 这个问题,最终牵出了系统两个月来从未被发现的七个根因。 KANet 是什么? KANet 是建立在 Kaspa 区块链上的多智能体自治系统。它的核心理念:利用 Kasia 协议(一个建立在 Kaspa L1 上的加密 P2P 消息层),让 AI Agent 能够通过区块链进行通信、交易撮合、和自主决策。 每一条消息,都是一笔链上交易。每一次握手,都有链上记录。每一笔 OTC 交易,全程上链,无需信任中间人。 这是"协议即市场"的具体实践。 调查开始: 问题看起来很简单:为什么用户的消息没有被处理? 按照六层调查法,从最基础的地方开始: 第一层,看真实数据: -- 用户地址在 relation_states 里是什么状态? SELECT * FROM relation_states WHERE peer_address LIKE '%qrg6g43%'; -- 结果:status = accepted,握手已完成。 -- messages 表里有没有这条消息? SELECT * FROM messages WHERE conversation_id LIKE '%qrg6g43%'; -- 结果:没有 4/4 的记录 数据清楚了:消息在链上,但 KANet 不知道它的存在。 根因 1:系统没有记忆 KANet 的 Scout 模块负责扫描 Kaspa 区块链。但它用的是 subscribeBlockAdded——只接收订阅之后的新块,不回扫历史。 系统重启后,Scout 从当前块开始监听。00:52 那个块,已经是"过去",永远不会再被扫到。 更根本的问题:Scout 没有持久化"上次扫到哪里"。 它没有记忆。每次重启,都像第一天。 修复思路:不能用全量回扫(Kaspa 10 BPS,停机 30 天的数据量是天文数字)。而是用一个更优雅的方案:按地址查询。 // 不扫块,按地址查历史 TX // 停机 30 天也只需几秒 GET api.kaspa.org/addresses/{myAddress}/full-transactions?after={lastSeen} 这正是 Kaspa 的设计哲学:UTXO 模型天然支持按地址查询,不需要遍历所有块。 根因 2:消息解密了,但找不到发送方 历史补全机制建好了。系统重启,找到了用户的消息,解密成功——但 Martin 的 Relay 报了一行日志: [Martin] RX 30c459... 你好! [Martin] unknown sender — skipping ingest and reply 解密成功,但不知道是谁发的。 Kasia 的 comm 消息是 self-send 协议:发送方把消息加密后发给自己,接收方通过 ECDH 共享密钥解密。消息里不直接包含发送方地址,而是包含一个 alias——从共享密钥派生的短标识。 KANet 的 findAddressByAlias 函数会遍历所有认识的地址,本地派生 alias,和消息里的 alias 对比。 结果:94 个地址,全部不匹配。 Martin 本地派生:2cbcb7bb9098 TX 里的实际 alias:5f5de35a24f7 为什么? 根因 3:跨钱包不兼容 Kasia 协议的设计文档里有一行注释:# chain.mjs:95 "Prefer alias from on-chain handshake over locally derived (cross-wallet compat)"。不同的 Kasia 客户端,alias 派生算法可能不同。协议的正确做法是:握手时双方交换 alias,后续用对方握手时给出的 alias,不做本地派生。 KANet 知道这个原则吗? 查了一遍整个 Console 代码库:grep -rn "alias" kasia-console/src/ # 结果:0 行匹配 Console 完全不知道 alias 的存在。 根因 4:两个月来,alias 每次都被丢弃 追踪代码,找到了握手处理的位置:// rpc-listener.mjs:421;const parsed = JSON.parse(decrypted); log('HANDSHAKE from', senderAddress, '— alias:', parsed.alias); // ← 然后就没有然后了 parsed.alias 打完日志,就被丢弃了。 没有传给 ingestHandshake。没有传给 Console。没有存入任何数据库表。relation_states 表里没有 their_alias 字段。 这个遗漏存在于系统第一天起。 两个月,每一次握手,alias 都被丢弃。每一个来自不同钱包的用户,comm 消息都无法识别发送方。 修复的关键链路找到根因,修复反而简单: 握手时 parsed.alias(已经在手了) 传给 ingestHandshake(加一个参数)--> Console 存入 relation_states.their_alias(一个新字段)--> findAddressByAlias 直接查这个字段(不再本地派生) --> senderAddress 有值--> ingestMessage 写入正确 conversation--> Brain 回复--> 用户收到消息 五个文件,信息链路补全。 验证结果 系统重启,catch-up 机制触发: [Martin] catch-up: found 27 pending historical comm TX [Martin] RX 30c459... 你好! [Martin] findAddressByAlias: found kaspa:qrg6g43... [Martin] ingestMessage: writing to conversation 1b165836 [Martin] replyToMessage: sending reply... 通讯录 UI 里出现了: 04-04 00:52 "你好!" 04-04 05:26 "你好!握手成功,我是 Martin,很高兴认识你..." 用户在链上收到了回复。 这一天真正发生了什么 表面上,修复了一条丢失的消息。 实际上,重建了系统的地基:根因 、影响、 修复, Scout 无检查点 停机期间所有消息永久丢失 ,检查点持久化 历史补全 , alias 链路断裂 跨钱包用户消息永远无法识别 ,alias 沿链路传递 , 判断顺序反了 ,持续产生孤立数据 ,先判断再 ingest ,数据源选错 ,本地派生跨钱包不兼容 ,查 relation_states , Console 不知道 alias 系统性遗漏 ,新增 their_alias 字段 , 脏数据阻断 UI 无法正确显示, 清理并补写 history-fetcher 缺失, 停机后无法自动恢复 ,新建按地址查询机制……若干遗留进两个月问题,一天打通。 AI 协作开发的真实样子 这个项目用 Claude Code 作为主要的编程智能体。今天是个转折点——不是因为 AI 更聪明了,而是因为工作方式对了: 之前的模式:给 AI 一个模糊目标,AI 自由发挥,搞了一套新链路,和现有系统矛盾,产生更多 bug。两个月,瞎子摸象。 今天的模式:六层调查法,从真实数据开始,任务文档精确到函数名和行号,两道强制检查 Agent(数据一致性 架构约束),先读系统,再动手;有疑问,停下来等确认 AI 的能力没有变。提问的方式变了,约束的方式变了。 关于 KANet 自由市场。今天修复的,是 KANet 通信层的底层问题。KANet 自由市场正在建设中:任何两个地址,可以广播任意标的的买卖意愿。KAS 换 USDT 是第一笔验证。下一步,是其他标的换 KAS,是服务换 KAS,是任何两个人愿意互换的东西。 协议不审判标的。协议只保证:广播了,可查;达成了,上链;完成了,不可篡改。 没有交易所,没有做市商,没有 KYC。两个节点,握手成交。 这是 Kaspa 哲学在应用层的投影。KAS-USDT 是一束微光,协议地基已经在了。 KANet 开发日志,2026年4月4日 Kaspa 区块链,10 BPS,永不停歇

1
2
10
487