
模拟结果要连同读取版本一起看
做区块链审计评估的资料核对时,可以先选一笔具体交易,检查它依据哪个状态计算、通过了哪些验证、最终更新了什么。本文讨论Fabric文档中的读写集语义,不执行漏洞扫描,也不把并发冲突率直接当作系统安全评分。模拟成功只是流程中的一个结果,后续仍有验证。
Fabric在背书节点模拟交易时生成读写集。读集保存读过的键及其已提交版本,不保存对应值;写集保存准备写入的键与新值。一次交易多次写同一个键时,只保留最后写入值。读集中的版本因此是定位冲突的重要依据,不能只留业务输入和计划写入结果,把计算所依赖的状态线索删掉。
同一旧版本可以产生两个待验证结果
假设教学账本里只有一个库存键K,两笔交易甲、乙都在同一旧状态上读取K的版本,再分别算出准备写入的值。这里不使用真实库存,也暂且假定两笔交易都满足背书等其他条件。随后它们按甲在前、乙在后的顺序进入同一区块;进入这个顺序,并不会让乙自动重新读取甲的结果。
验证甲时,若它读到的版本仍与当前版本一致,甲可以通过这一检查,写集用于更新K的值与版本。验证乙时,Fabric还会考虑同一区块内排在前面的有效交易;乙读集保留的旧版本已与K的新版本不同,因此无法通过版本检查。不能把两个模拟得到的数值顺次覆盖,就声称已经复现了原验证过程。

无效标记与未应用写集需要一起保留
Fabric的交易流程说明,区块中的交易会被标记为有效或无效,节点把区块追加到账本,但只有有效交易的写集才进入当前状态数据库。因此,在上述限定例子里,两条交易记录仍可进入区块,乙的计划写入却不应被当作已经生效。记录数量和实际状态变化,应分别核对。
这也不是所有同时写同一键的交易都会冲突。读写集示例表明,不读取相关键的写入并不会凭空带上同样的旧版本依赖。诊断具体失败时,要依据该笔交易实际读过的键、版本和验证结果,不能仅凭两个操作的业务名称相同,就把原因都归结为多版本并发控制冲突。
数据库对照只能解释各自的失败语义
PostgreSQL十七版提供了一个有限对照:在Repeatable Read隔离级别,事务使用首次非事务控制语句开始时的快照。若它要更新的行已被另一并发事务实际修改并提交,可能因并发更新发生序列化失败;文档要求中止当前事务并从头重试整个事务。这个条件不能套给所有隔离级别,也不是Fabric按区块验证的同一流程。
资料表可据此分别保存模拟或查询依据、失败反馈,以及最终提交结果。PostgreSQL的事务重试要求,不能被移植成对Fabric旧交易原样重发必然成功的保证;重新处理时仍需遵守各自应用条件。本文没有运行数据库或提交交易,甲、乙、K仅用于说明怎样把失败原因与实际状态对应,不构成对任何项目的审计结论。