区块链(28):索引器怎样在断线与重组后重算订单
合约事件订阅停止五分钟,重连后只恢复 WebSocket 会漏历史;仅从上次高度回填又可能把已处理事件算两次。区块链(27):响应丢失时不能凭交易哈希重做订单保存的是发送意图,本篇保存可撤销的链上观察。索引应把 cursor(高度+块哈希)、事件定位键和业务投影更新放进同一数据库事务;回填按块哈希验证祖先,必要时撤销断开的分支再重放新链。
flowchart LR
B[按高度拉块/收订阅] --> H[核对父哈希与本地游标]
H -->|连续| T[事务写事件键、订单投影和 cursor]
H -->|分叉| U[按分支撤销投影]
U --> B
T --> R[对账: 当前合约状态和资产余额]
事件唯一性不能只用 txid:同笔交易可有多个日志,重组后同逻辑交易还可能进入另一块。至少记录链身份、区块哈希、交易/日志位置和合约地址,并规定同一订单只被现行规范历史上的合法事件推进。数据库事务提交前宕机应重新读本块;提交后回放应被唯一键去重。若订单已发货又遇撤销,只回滚数据库标签不足以追回实物,需风险窗口与人工补偿。
重组撤销的是来源,不是凭空减去金额
合成模型把块高度、哈希、父哈希及 (块哈希, tx 标识, 日志序号) 存入 SQLite;同一键重复输入不增加计数,同一键换金额则拒绝。测试在写入一块后关闭连接,重开并回放同块,投影仍只有一笔。真实链接入还必须把 chain ID、合约地址、交易在块内位置纳入唯一键;测试中的文本哈希与深度 2 无共识含义。
模拟分叉按已存的共同祖先删除分叉后的来源事件与块,再从新分支重放。旧块订单价值 70 从“满足深度”变为 0;在新分支重新插入付款事件并积累足够模型深度,才恢复为 70。伪祖先或错误父链接在同一事务内报错,原分支不被半删除。它验证的是给定规范链输入时索引的撤销算法;模型不会判断哪条历史是真正的规范链,更不验证执行回执或终局。
练习一:游标先加一再更新订单,进程在中间退出,留下什么缺口?答案:旧块不再回填而业务投影缺失;两者必须原子提交。练习二:同高度块哈希变化但新块没有原事件,投影该如何处理?答案:先撤销旧分支派生状态,再从共同祖先重放;不能只增加 confirmations 字段。SQLite 有限模型的原始输出见 examples/blockchain/evidence/27-28-38/;链上重复事件、中断与真实重组注入 NOT_RUN。
可迁移原则:可恢复观察需要可复算的来源与一致的提交边界。参考:Ethereum 日志 JSON-RPC、The Graph 官方文档(资料待核);导航:区块链(27):响应丢失时不能凭交易哈希重做订单 · 28 · 区块链(29):预言机能提交数据,不能把现实交付变成定理。



