形式化方法与程序验证
形式化方法与程序验证近二十年的变化不应写成工具清单。真正被换掉的是评价标准:系统不再只凭单点分数、平均速度或“能运行”证明自己,而要说明在并发库、编译器、内核、云配置和学习组件共同构成的软件栈中,规范缺口、可信基、环境假设和状态爆炸怎样进入结果。上一个十年主要把旧默认拆成可测约束;这十年则经历真实部署与方法清算,要求同时报告反例、覆盖性质、证明时间和未证明部分。下面二十条均按主证据年份归幕,每条给出源行、六段证据链和可抽取的碰撞行。
第一幕把验证从手工推导推进到共享求解器、可组合分析与工业级端到端案例。 本幕八条共同把旧默认第一次放到可测上界、误差、资源或行为证据上,并试写出可与别的领域换算的分母。
甲、SMT求解器:验证问题应下沉为可判定约束
在统一求解器出现以前,每一种验证工具都自带一套推理引擎:模型检查器有自己的判定过程,静态分析器有自己的抽象域,定理证明器有自己的策略库。默认前提是「推理能力属于工具本身」,于是任何一处引擎的进步都无法被别的工具继承。这条转向把验证义务下沉成一种共同的可满足性语言,推理能力从各家自建变成公共基础设施,工具竞争的位置随之上移到如何编码问题,而不是如何解约束。
这条理论的可反驳命题是:把位向量、数组、线性算术和未解释函数交给统一的可满足性模理论求解器,可让多种验证前端共享自动推理核心。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“可判定约束数/总验证义务数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自de Moura 与 Bjørner,2008年《TACAS会议录》LNCS 4963:337–340。具体设计与读数是:Z3在同一求解核心里组合位向量、数组、线性算术和未解释函数;验证前端只需把程序语义翻成约束,而不必各自重写推理器。Z3于2008年公开并进入程序分析、测试和模型检验;SMT-COMP持续比较显示,组合理论求解能力在2010年代快速扩展。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“规范是否写出了真正业务意图”。对照证据见Bradley,2011年《VMCAI会议录》LNCS 6538:70–87:IC3维护一列逐步加强的框架F0到Fk,并学习阻断坏状态的归纳子句;深度不再等同于必须展开的时间步数。它显示可信基仍可能大到不可审计;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:一个验证工具应报告有多少义务真的被判定,有多少被超时、被近似或被人工旁路。只说「已验证」而不给判定率,读者无法分辨结论来自证明还是来自放弃。求解器的版本、随机种子与超时阈值也因此成为结果的一部分——同一份义务换一个版本可能就从判定变成超时。
与本块第十五条《可检查证明证书》构成一对制衡:本条把推理集中到一个高度优化的大型求解器上,第十五条要求这个求解器的结论必须能被一个小到可以人工审阅的内核复查。集中带来能力,也带来单点信任;两条不同时执行时,最常见的结果是整条证明链的可信度悄悄压在一个几十万行、没人逐行读过的程序上。
乙、性质导向可达性:不必枚举完整状态空间
模型检查早期的默认路线是把状态空间尽量完整地表示出来再搜索:符号编码、有序决策图、抽象细化,都在处理同一个负担——状态数随变量指数增长。这个前提把「验证一条性质」化约成「先掌握整个系统」。性质导向可达性改写了这个顺序:不再先建立系统全貌,而是从待证性质出发反向学习足以阻挡坏状态的归纳子句,只在必要处展开状态。
这条理论的可反驳命题是:IC3/PDR直接学习阻止坏状态的归纳子句,以性质为中心构造不变量。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“实际探索状态数/理论状态总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Bradley,2011年《VMCAI会议录》LNCS 6538:70–87。具体设计与读数是:IC3维护一列逐步加强的框架F0到Fk,并学习阻断坏状态的归纳子句;深度不再等同于必须展开的时间步数。Bradley于2011年提出IC3;随后在硬件与软件模型检验竞赛中表现突出,证明许多深状态系统可在不显式遍历全图时收敛。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“求解器结果能否由小内核复查”。对照证据见CHC-COMP组织者,2018年起《Horn Clauses for Verification and Synthesis》竞赛报告,页2018–2024:竞赛把线性、非线性、数组和循环不变量等类别放进统一格式;同一求解器能跨前端比较成功率、超时率和证书,而非只看单个案例。它显示自动化提示会制造看似完整的证明脚本;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:报告验证成功时要说明实际探索了多大比例的状态空间,以及所得不变量的形态与规模。一句「性质成立」若不附带不变量,使用者既无法复查,也无法在系统改动后判断该结论是否还站得住。工业验收因此要求把学到的不变量作为制品交付,而不只是交一个布尔结论。
与本块第十一条《约束Horn子句》做的是同一件事的两种记法:本条把不变量学习绑定在硬件式的转移系统上,第十一条把它抽象成可由多种前端共享的子句形式。两者的分歧在于通用性与效率的取舍——统一记法让不变量求解可以跨语言复用,专用算法则在特定结构上快出一个数量级;同一道题在两条路径上的可解性并不一致。
丙、双向蕴含与分离逻辑:缺失前提也可自动推断
过程间内存分析长期卡在一个前提上:要分析一个函数,必须先知道调用者提供了什么样的堆。于是分析要么自顶向下依赖完整程序,要么要求人工为每个函数写前置条件。在百万行代码上这两条路都走不通。双向蕴含改写了这个前提——从函数体内的堆操作反推它需要什么、剩下什么,前置条件由推断得到而不是由人提供,模块化分析因此第一次能在真实代码库上跑起来。
这条理论的可反驳命题是:分离逻辑的双向蕴含可从堆操作反推需要的资源与残余状态,使模块化内存分析扩展到大代码库。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“自动推断前置条件数/人工提供前置条件数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。
主证据来自Calcagno、Distefano、O’Hearn 与 Yang,2009年《POPL会议录》:289–300,页289–300。具体设计与读数是:分析同时推断缺失前置资源与执行后剩余资源,由此生成可复用过程摘要;工业实现后来可在数百万行代码上按提交增量运行。Calcagno等在2009年前后提出bi-abduction;Infer在2010年代中期用于移动应用和大规模工业代码审查,证明局部摘要可持续复用。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“抽象是否漏掉关键并发交错”。对照证据见Rondon、Kawaguchi 与 Jhala,2008年《PLDI会议录》:159–169,页159–169:系统把候选谓词限制在有限限定词集合,再交由SMT推断;数组下标、长度和数值范围因此能在普通类型检查路径中被自动验证。它显示证明可能只对错误规范成立;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:报告缺陷时必须给出推断出的前置条件,让开发者能判断这条警告是真缺陷还是分析器假设了不可能的调用环境。缺了这一项,误报无法被有效归类,工具很快会被开发流程排斥。相应地,工具的成绩也应按「被开发者接受并修复的报告数」计,而不是按报告总数计。
与本块第四条《精化类型》分工相反:精化类型要求程序员把性质写进类型再由求解器检查,本条不要求程序员写任何东西而由分析器反推。前者的保证更强、覆盖面由人决定;后者能扩到整个代码库、但保证只到分析器的抽象为止。同一份代码上两者给出的「安全」不是同一件事,混用会高估已获得的保证。
丁、精化类型:类型检查可以携带值级性质
类型系统与程序验证长期是两拨人的事:类型管的是形状,值层面的性质要另起炉灶写规范、开定理证明器。这个默认让验证成为一道额外工序,只有关键项目才付得起。精化类型把逻辑谓词嵌进类型,让边界、协议状态与不变式随普通的类型检查一起被检验——验证从独立工序变回编译流程的一部分,代价是这些谓词必须落在自动求解器判得动的片段里。
这条理论的可反驳命题是:把逻辑谓词嵌入类型并交给自动求解器,可在接近普通编程的工作流中验证数组边界、协议状态和不变量。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“由类型检查阻止的违规路径数/总潜在路径数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。
主证据来自Rondon、Kawaguchi 与 Jhala,2008年《PLDI会议录》:159–169,页159–169。具体设计与读数是:系统把候选谓词限制在有限限定词集合,再交由SMT推断;数组下标、长度和数值范围因此能在普通类型检查路径中被自动验证。Rondon、Kawaguchi与Jhala于2008年提出Liquid Types;随后Liquid Haskell等展示复杂不变量可由注解与推断共同完成。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“端到端证明是否仍依赖未验证工具链”。对照证据见Jung、Krebbers、Jourdan、Bizjak、Birkedal与Dreyer,2018年《Journal of Functional Programming》28:e20,DOI:10.1017/S0956796818000151:期刊版用73页统一呈现资源代数、不变量、幽灵状态和高阶并发推理;同一逻辑框架可组合验证细粒度并发库而不重建整套语义。它显示可组合逻辑的工程成本可能超过缺陷风险;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:声明「类型已保证」时要写清保证落在哪一层——形状、边界,还是完整的功能规范。三者的强度差得很远,混着说会让下游误以为拿到了功能正确性。同时应报告有多少注解是人写的、多少是推断的,因为注解负担正是这条路线能否规模化的真实读数。
与本块第一条《SMT求解器》是使用者与被使用者的关系,却在一处发生冲突:精化类型要求谓词保持在可判定片段内,而实践中最想表达的性质常常越界。于是语言设计要么削弱表达力以保证判定,要么允许越界并接受超时。这个取舍不在求解器一侧,而在类型系统的设计者手上,任何一方单独优化都无法消除它。
戊、验证编译器:优化器也属于证明对象
高层证明长期默认编译器是可信的:源程序被证明正确,机器码就被认为同样正确。这个前提把优化器整体排除在证明对象之外,而优化器恰恰是整条工具链里改动最频繁、假设最微妙的部分——未定义行为的处理、别名假设、指令重排都可能让源层成立的性质在机器码上不再成立。这条转向要求编译器为每一次转换给出保持语义的证明,编译从工程实现变成证明对象。
这条理论的可反驳命题是:编译器必须证明每个转换保存源语义,否则高层证明可能在生成机器码时失效。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“经证明保持语义的优化数/总启用优化数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Leroy,2009年《Communications of the ACM》52(7):107–115。具体设计与读数是:CompCert为主要编译阶段给出语义保持证明;后续Csmith随机测试在GCC和LLVM中发现数百个错误,而CompCert已验证核心没有出现同类错误代码。CompCert自2006年起以Coq证明C编译器主要阶段,2009年前后形成完整成果;测试发现其生成代码可靠性显著高于未验证编译器,但只覆盖已形式化。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“学习组件的连续输入域能否被有限覆盖”。对照证据见Lopes 等,2015年《PLDI会议录》,ACM:Alive把334条LLVM局部优化转成可检查条件,并找出其中八条不正确规则;这表明“成熟优化库”仍需逐条翻译验证。它显示工业系统持续变化会使证明迅速过期;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:任何端到端的正确性声明都必须说明它止于哪一层——源码、中间表示,还是机器码,以及未被证明的那几层由什么承担。同时应报告有多少启用的优化是被证明保持语义的,因为常见做法是关掉未验证的优化以换取证明,那样的性能读数与生产配置并不对应。
与本块第七条《翻译验证》是同一目标的两条路线:本条一次性证明编译器对所有输入正确,第七条只核验这一次编译结果。前者代价集中在编译器开发上,一旦证成即长期受益;后者代价分摊到每次编译,却能用在未被证明的成熟编译器上。两条路线的可信基与运行开销都不同,选哪条应按可信基记账来算,不按直觉。
己、微内核全功能正确性:系统软件可以细化到机器码边界
操作系统内核长期被默认为「太大、太底层、太依赖硬件」而无法形式化验证:内核要处理中断、页表、汇编与并发,抽象一旦下沉到这些细节,证明规模就被认为会失控。这个前提把可验证性限定在小型算法与协议上。这条转向证明了它不成立——通过抽象规范、可执行实现与机器级模型之间的逐层细化,真实内核的所有执行都可以被机器检查地对上规范。
这条理论的可反驳命题是:通过抽象规范、可执行实现与机器级模型的逐层细化,可证明真实微内核所有执行都符合规范。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“机器检查的内核代码行/系统总代码行”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。
主证据来自Klein 等,2009年《SOSP会议录》:207–220,页207–220。具体设计与读数是:团队证明约8700行C内核的所有执行细化抽象规范,证明脚本约二十万行Isabelle,工程投入约二十人年;规模本身成为可核对读数。seL4团队于2009年公布约8700行C代码的功能正确性证明,之后扩展完整性与机密性;百万级证明工程同时暴露规范与硬件假设的边界。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“规范是否写出了真正业务意图”。对照证据见Hawblitzel 等,2015年《SOSP会议录》:1–17,页1–17:IronFleet把协议规范、实现代码和网络环境放进一条Dafny证明链,同时覆盖安全性与活性;验证对象是真实可运行的复制服务而非小模型。它显示可信基仍可能大到不可审计;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:说「已验证」时必须给出验证边界——哪些汇编、哪些硬件假设、哪些初始化代码在证明之外。这些例外不是脚注,它们决定了这份保证在实际部署中还剩多少。同时应公开证明与代码的行数比,因为这个比值是后来者估算同类工程可行性的唯一现实依据。
与本块第十九条《可信基记账》互为前提:本条把机器检查的范围推到内核边界,第十九条要求把边界之外的东西逐项列出来计价。缺了后者,「已验证内核」这个说法会在传播中膨胀成「整机可信」;而实际留在可信基里的编译器、硬件模型与人工步骤,往往比被证明的部分更容易出错。
庚、翻译验证:不必证明整个优化器,只需核验每次结果
证明编译器正确的默认路径是证明程序本身:一次性证明所有输入下所有转换都保持语义。这条路径的代价决定了它只能用在专门为验证而写的编译器上,而工业界用的是几百万行、每周都在改的成熟编译器。翻译验证换了个提问方式——不问「这个编译器总是对的吗」,而问「这一次编译的输出与输入等价吗」,把不可承受的一次性证明改成每次编译都做的可检查核验。
这条理论的可反驳命题是:可为每个编译结果生成可检查的等价性条件,验证这一次转换是否保持语义。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“每次编译的验证时间/编译总时间”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Lopes 等,2015年《PLDI会议录》,ACM。具体设计与读数是:Alive把334条LLVM局部优化转成可检查条件,并找出其中八条不正确规则;这表明“成熟优化库”仍需逐条翻译验证。Alive于2015年前后把LLVM peephole优化写成可验证规则并发现多处错误;它显示翻译验证能覆盖快速演化的优化库,但依赖精确的中间语义。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“求解器结果能否由小内核复查”。对照证据见Tan 等,2019年《Journal of Functional Programming》29:e2:CakeML证明链穿过十二种中间语言并覆盖五类目标体系结构,还完成自举编译;可信断点由“编译器之后”继续向运行时与机器模型下移。它显示自动化提示会制造看似完整的证明脚本;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:报告核验覆盖率与每次编译增加的时间,并说明未通过核验时的处置是拒绝、降级还是仅告警。核验若默认告警且被忽略,等于没有核验。相应地,构建系统的日志应保留每次核验结论,使得任何一份二进制都能回溯到当时的等价性检查记录。
与本块第五条《验证编译器》互为替代,与第十五条《可检查证明证书》共享同一套思路:都是把「相信一个大工具」改成「检查它交出的这一次结果」。这条思路的通用代价是核验器本身成为新的信任点——核验器越强大就越可能出错,越简单就越常在合法的优化上报警,取舍点必须写明而不能默认。
辛、分布式系统机器证明:安全性与活性必须一起交付
分布式协议的形式化长期停在协议层:在纸上或模型检查器里验证一个共识算法的安全性,然后由工程师手写实现。这个默认假设实现忠实于协议,而绝大多数真实故障恰恰发生在这个假设破裂的地方——重试、超时、序列化与状态持久化都不在协议模型里。这条转向要求把消息模型与故障模型写进规范,并对真实实现同时证明安全性与活性,两者缺一都不构成可部署的保证。
这条理论的可反驳命题是:真实分布式实现应同时证明状态不变量、安全性、终止或活性,并把消息与故障模型写进规范。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“已证明安全与活性性质数/规范总性质数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Hawblitzel 等,2015年《SOSP会议录》:1–17,页1–17。具体设计与读数是:IronFleet把协议规范、实现代码和网络环境放进一条Dafny证明链,同时覆盖安全性与活性;验证对象是真实可运行的复制服务而非小模型。IronFleet于2015年用Dafny验证非平凡复制服务,涵盖实现代码的安全性和活性;代价是大量辅助引理与严格环境假设。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“抽象是否漏掉关键并发交错”。对照证据见Ringer 等,2019年《Foundations and Trends in Programming Languages》5(1–2):1–218:大规模证明工程复盘把库升级、自动化脆化、接口重构和证明性能列为持续成本;证明仓库必须像代码仓库一样跑回归。它显示证明可能只对错误规范成立;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:交付时要分别列出已证明的安全性性质与活性性质,并写明所假设的故障模型与消息模型。只证安全不证活性的系统可以用「永不响应」来满足全部要求,这类退化在实验室里不会暴露。同时要说明证明覆盖的是协议、实现还是部署配置——三者的差距正是事故常发的地带。
与本块第九条《并发分离逻辑》处理的是同一种困难的两种尺度:一个在共享内存的线程之间,一个在网络分割的节点之间。两者都需要把局部推理组合成全局结论,但可用的假设不同——共享内存有内存模型可依,分布式只有消息与超时。把一侧的直觉搬到另一侧,是这类证明里最常见的错误来源。
第二幕不再只问“能否证明”,而是追问证明覆盖什么、遗漏什么、谁来复查以及如何持续更新。 本幕十二条更关注部署、公开清算与方法自审,尤其要求把平均分数换成分布、边界、长期读数和责任链。
一、并发分离逻辑:共享状态需要可组合的幽灵协议
并发程序的推理长期在两个极端之间摇摆:要么假设全局锁而丧失性能,要么逐个交错枚举而丧失可扩展性。默认前提是共享状态无法被局部化,因此线程局部的推理不能组合成全局结论。并发分离逻辑改写了这一点——用资源代数、幽灵状态与不变量协议把「谁在什么时候拥有什么」显式化,线程可以各证各的,再按协议拼成全局正确性。
这条理论的可反驳命题是:资源代数、幽灵状态和不变量协议可把线程局部推理组合成全局并发正确性。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“局部资源不变量数/全局共享状态数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。
主证据来自Jung、Krebbers、Jourdan、Bizjak、Birkedal与Dreyer,2018年《Journal of Functional Programming》28:e20,DOI:10.1017/S0956796818000151。具体设计与读数是:期刊版用73页统一呈现资源代数、不变量、幽灵状态和高阶并发推理;同一逻辑框架可组合验证细粒度并发库而不重建整套语义。Iris自2015年后形成通用高阶并发分离逻辑,并用于Rust语义、并发库与弱内存研究;表达力增强也提高了证明设计门槛。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“端到端证明是否仍依赖未验证工具链”。对照证据见Calcagno、Distefano、O’Hearn 与 Yang,2009年《POPL会议录》:289–300,页289–300:分析同时推断缺失前置资源与执行后剩余资源,由此生成可复用过程摘要;工业实现后来可在数百万行代码上按提交增量运行。它显示可组合逻辑的工程成本可能超过缺陷风险;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:说明所用的幽灵状态与不变量协议是什么,因为这些构造决定了证明能覆盖哪些交错。协议本身是设计选择而非客观事实,不公开就无法复查。同时应报告局部不变量与全局共享状态的数量比,它是判断这套证明是否真的做到模块化的直接读数。
与本块第十三条《超性质验证》在同一处分岔:并发分离逻辑证的是每一条执行都满足性质,超性质要比较多条执行之间的关系。信息流与不干扰这类要求无法写成单轨迹性质,因此再完整的并发正确性证明也不蕴含机密性。两者被混为一谈时,最典型的后果是把「无数据竞争」当成了「无信息泄露」。
二、验证密码软件:数学算法正确不等于实现安全
密码学实现长期依赖一个分层默认:算法的安全性由密码学家证明,实现的正确性由工程师测试。这个前提在两层之间留下了一整类漏洞——内存越界、分支依赖密钥、编译器把常数时间代码优化成变时间代码,都不属于算法问题,却足以让数学上的安全性归零。这条转向要求功能正确、内存安全与常数时间在同一份实现上一并被验证,并把编译链本身纳入边界。
这条理论的可反驳命题是:实现必须把功能正确、内存安全、常数时间与编译链边界一并验证。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“同时通过功能与侧信道核验的实现数/实现总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Zinzindohoué 等,2017年《CCS会议录》:1205–1222,页1205–1222。具体设计与读数是:HACL*从F*规范生成C代码,并同时证明功能正确、内存安全和秘密相关分支约束;验证结果最终进入浏览器与系统密码组件。HACL*、EverCrypt在2017年后用F*生成并验证高性能密码实现,进入Firefox、Linux等生态;证明仍依赖微体系结构侧信道模型是否充分。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“学习组件的连续输入域能否被有限覆盖”。对照证据见Cutler 等,2024年《Proceedings of the ACM on Programming Languages》8(OOPSLA1):670–697:Cedar为策略求值、类型检查和授权分析给出精确定义,并用差分测试核对多种实现;权限配置从文本约定变成可执行、可查询的程序。它显示工业系统持续变化会使证明迅速过期;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:安全声明必须写明覆盖了哪几项——功能、内存、时序、编译产物,而不是笼统地说「经过形式化验证」。同时要给出验证在哪一级产物上完成:源码级的常数时间保证不自动传递到优化后的机器码,这一段落差必须由工具链证据补上,否则声明就止于源码。
与本块第五条《验证编译器》是彼此的必要条件:密码实现的时序性质恰恰是最容易被优化器破坏的一类,而验证编译器的价值也最先在这类性质上被兑现。两条分开做时会出现一种典型的落空——源码经过严格验证,编译时却使用了未被证明保持时序特性的优化,结果是纸面保证完整而实测仍可被侧信道攻破。
三、约束Horn子句:多种验证任务可以共享不变量求解
不同验证任务长期各写各的求解流程:程序验证要合成循环不变量,模型检查要找归纳不变式,抽象解释要选抽象域,彼此的进展互不相通。默认前提是「不变量合成属于各自的前端」。约束Horn子句改写了这个前提——把程序语义与未知的不变量一起编码成一种共同的子句形式,不变量合成从各家自建变成一个可以被独立求解器竞赛式改进的公共问题。
这条理论的可反驳命题是:把程序语义与未知不变量编码成受约束Horn子句,可由统一求解器合成归纳关系。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“求得不变量的义务数/Horn子句义务总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自CHC-COMP组织者,2018年起《Horn Clauses for Verification and Synthesis》竞赛报告,页2018–2024。具体设计与读数是:竞赛把线性、非线性、数组和循环不变量等类别放进统一格式;同一求解器能跨前端比较成功率、超时率和证书,而非只看单个案例。Spacer、SeaHorn及CHC-COMP在2016年后推动该范式;竞赛结果显示统一编码有效,但非线性算术和复杂堆仍是难点。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“规范是否写出了真正业务意图”。对照证据见Cruz-Filipe 等,2017年《CADE会议录》LNCS 10395:220–236:LRAT把求解器结论变成独立小内核可重放的推导;核验器代码规模远小于高性能SAT求解器,可信基因而可以单独审计。它显示可信基仍可能大到不可审计;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:报告求得不变量的义务比例,并公开所用的编码方式。同一段程序可以有多种子句编码,难度相差很大,不写清楚就无法比较两个求解器的强弱。竞赛式评测也因此必须公布题目来源与编码脚本,否则排名衡量的是编码技巧而不是求解能力。
与本块第二条《性质导向可达性》是通用与专用之争的另一面,与第一条《SMT求解器》则是同一趋势在不同层次上的重复:约束下沉到公共语言,能力集中到公共求解器。这个趋势的代价一致——前端为迁就公共语言而损失结构信息,而结构信息往往正是特定领域里最有效的剪枝依据。
四、神经网络验证:学习组件也应接受反例搜索
机器学习组件进入系统之后,正确性讨论一度默认交给测试集准确率:在留出集上表现好,就算这个组件可用。这个前提假定测试分布覆盖了部署时会遇到的输入,而对抗样本表明,在任一样本的微小邻域内就可能存在改变输出的点,这些点不会出现在任何采样出来的测试集里。这条转向把学习组件当作证明对象——对给定的扰动集合与输出性质,检验是否存在反例,而不是统计有多少样本恰好答对。
这条理论的可反驳命题是:对给定扰动集合和输出性质,可用线性松弛、分支定界或SMT检验是否存在对抗反例。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“已验证输入区域体积/允许输入域体积”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Katz 等,2017年《CAV会议录》LNCS 10426:97–117。具体设计与读数是:Reluplex检查ACAS Xu的45个网络和多项安全性质,在连续扰动区域内寻找反例;验证结果因此是“此性质在此集合内成立”,不是测试集准确率。Reluplex于2017年验证ACAS Xu网络,随后VNN-COMP形成年度基准;可验证规模不断扩大,但结果高度依赖网络结构与扰动模型。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“求解器结果能否由小内核复查”。对照证据见Yang 等,2023年《Advances in Neural Information Processing Systems》36:21573–21612:LeanDojo从Mathlib抽取近十万条定理与证明轨迹供模型检索,但每个候选证明仍必须由Lean内核逐步接受;生成成功率与逻辑正确性被分成两道读数。它显示自动化提示会制造看似完整的证明脚本;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:一项鲁棒性声明必须写明扰动集合的定义、半径与验证覆盖的输入区域比例。脱离扰动定义谈鲁棒性没有意义,因为不同范数下的结论互不蕴含。同时要区分「已证明不存在反例」与「未找到反例」——后者只是搜索预算的函数,不构成保证。
与本块第十八条《规范错位》在这里最尖锐地相遇:神经网络验证能严格证明的,往往只是输入邻域内的输出稳定,而使用者真正关心的性质(不歧视、不越权、符合业务意图)无法写成这种形式。证明得越严格,越容易让人忘记被证的并不是所关心的那件事——这正是形式化在学习系统上最典型的错位。
五、超性质验证:一次运行正确不代表多次运行关系正确
形式化性质长期默认是单轨迹的:给定一次执行,判断它是否满足要求。这个前提对功能正确性够用,却装不下一整类要求——机密性要求高机密输入的差异不体现在低机密输出上,差分隐私要求相邻两个数据库上的输出分布接近,公平性要求两个个体的处理可比。它们都不是关于一条执行的断言,而是关于多条执行之间关系的断言。这条转向把性质的量化层次从单轨迹提升到轨迹集合。
这条理论的可反驳命题是:信息流、非干扰与差分隐私等要求比较多条轨迹,应以超性质和轨迹量化逻辑表达。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“成对运行关系覆盖数/超性质要求总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Finkbeiner 等,2017年《Runtime Verification会议录》LNCS 10548:190–207。具体设计与读数是:HyperLTL以显式轨迹量词比较两次或多次执行,可表达非干扰和对称性;量词交替层数成为复杂度的直接读数。HyperLTL在2014年前后提出,2016年后出现模型检验与监控工具;量词交替会迅速放大复杂度。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“抽象是否漏掉关键并发交错”。对照证据见Ringer 等,2019年《Foundations and Trends in Programming Languages》5(1–2):1–218:大规模证明工程复盘把库升级、自动化脆化、接口重构和证明性能列为持续成本;证明仓库必须像代码仓库一样跑回归。它显示证明可能只对错误规范成立;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:写清楚被验证的性质需要比较几条执行、在什么变量上对齐。把超性质当成单轨迹性质来验证,会得到一个形式上成立而与原意无关的结论。相应地,工具的能力声明也要按「能表达几阶的轨迹量化」来标,而不是笼统地说支持信息流。
与本块第九条《并发分离逻辑》分处两个不同的方向:并发关心的是同一次执行内部的交错,超性质关心的是不同执行之间的关系。一个系统可以完全没有数据竞争而仍然泄露信息,也可以有竞争而不泄露。把二者放在同一张「安全性」清单里,正是许多安全评审给出错误结论的地方。
六、语言实现端到端证明:运行时与引导链不能留作黑箱
语言实现的证明长期停在编译器出口:源到目标的转换被证明保持语义,运行时库、垃圾回收、引导链与操作系统接口则默认可信。这个前提让证明链在最容易出问题的地方断开——运行时通常用不安全语言写成,引导过程涉及大量未被建模的初始化。这条转向要求把这些环节接进同一条证明链,让「已验证」指的是从源语义一直到机器执行的连续覆盖,而不是其中一段。
这条理论的可反驳命题是:可信语言栈应把源语义、编译器、运行时与机器执行连接成连续证明链。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“已证明启动链组件数/启动链组件总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Tan 等,2019年《Journal of Functional Programming》29:e2。具体设计与读数是:CakeML证明链穿过十二种中间语言并覆盖五类目标体系结构,还完成自举编译;可信断点由“编译器之后”继续向运行时与机器模型下移。CakeML在2014—2019年间实现经证明的ML方言、编译器与自举过程;它缩小可信基,却也限定了外部系统调用和硬件模型。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“端到端证明是否仍依赖未验证工具链”。对照证据见Gu 等,2016年《OSDI会议录》,USENIX:CertiKOS把约6500行C与汇编实现连接到约六十五万行Coq证明;未建模的硬件、引导代码和定理证明器内核被明确列入可信基账本。它显示可组合逻辑的工程成本可能超过缺陷风险;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:列出启动链的组件清单,并标明各自是被证明、被测试还是被假设。清单本身就是结论——没有清单的「端到端已验证」无法核对。同时应说明证明所依赖的机器模型版本,因为模型与实际处理器的差异是这类证明最后一处、也是最难被察觉的缺口。
与本块第十九条《可信基记账》几乎重合,但重心不同:本条尽力缩短未证明的部分,第十九条要求把仍未证明的部分明码标价。两条一起做才有意义——只做缩短会让人误以为已经归零,只做记账则容易把过大的可信基当成不可改变的现实接受下来。
七、可检查证明证书:求解器的‘SAT/UNSAT’不应靠声誉
求解器长期以布尔结论被使用:说可满足就给一个赋值,说不可满足就到此为止。前者可以当场验算,后者只能靠工具的声誉。这个不对称在几十万行的求解器上成了一个隐蔽的信任缺口——正是最强的那些优化最可能引入不健全的推理。这条转向要求不可满足的结论也交出可检查的证明证书,由一个小到可以被逐行审阅的内核独立复查。
这条理论的可反驳命题是:求解器应给出小型、确定、可由独立内核复查的证明证书。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“可由小内核复查的证书数/求解器结论总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Cruz-Filipe 等,2017年《CADE会议录》LNCS 10395:220–236。具体设计与读数是:LRAT把求解器结论变成独立小内核可重放的推导;核验器代码规模远小于高性能SAT求解器,可信基因而可以单独审计。DRAT/LRAT、SMTCoq与Alethe等在2016年后推动SAT/SMT证书化;证书可能巨大,生成、传输与检查成本仍是工程瓶颈。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“学习组件的连续输入域能否被有限覆盖”。对照证据见de Moura 与 Bjørner,2008年《TACAS会议录》LNCS 4963:337–340:Z3在同一求解核心里组合位向量、数组、线性算术和未解释函数;验证前端只需把程序语义翻成约束,而不必各自重写推理器。它显示工业系统持续变化会使证明迅速过期;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:报告有多少结论附带了证书、多少证书被独立复查通过,以及证书生成与复查各自的开销。只声明支持证书而不报复查率,等于把这道保证停在了功能列表上。同时应公布内核的规模,因为整条链的可信度最终等于这个内核的可信度,而不是求解器的。
与本块第二十条《机器建议、内核裁决》是同一条原则在两个时代的应用:不相信搜索过程,只检查搜索结果。区别在于对象——前者是求解器的推理步骤,后者是模型生成的证明脚本。原则相同,但风险不同:证书复查是机械的,而模型生成的证明若在规范一侧动了手脚,内核照样会通过。
八、云策略自动推理:权限配置本身是一种程序
云上的访问权限长期被当作配置来对待:一份份策略文档由人编写、由评审会读、靠经验判断有没有开得太宽。这个默认把权限当成文本而不是程序,于是「这份策略到底允许谁做什么」这个问题没有确定答案,只有解读。这条转向给策略语言配上形式语义,使可达权限、策略冲突与两份策略是否等价成为可以自动回答的问题,权限评审从人读文本变成机器判定。
这条理论的可反驳命题是:策略应有形式语义,可自动回答可达权限、冲突与等价性问题。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“自动发现越权配置数/策略配置总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Cutler 等,2024年《Proceedings of the ACM on Programming Languages》8(OOPSLA1):670–697。具体设计与读数是:Cedar为策略求值、类型检查和授权分析给出精确定义,并用差分测试核对多种实现;权限配置从文本约定变成可执行、可查询的程序。2019年后AWS等把SMT与模型检验用于网络和身份策略;Cedar于2022年公开精确定义的策略语言及验证工具,仍不能替代对组织意图的规范化。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“规范是否写出了真正业务意图”。对照证据见Zinzindohoué 等,2017年《CCS会议录》:1205–1222,页1205–1222:HACL*从F*规范生成C代码,并同时证明功能正确、内存安全和秘密相关分支约束;验证结果最终进入浏览器与系统密码组件。它显示可信基仍可能大到不可审计;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:交出自动发现的越权配置数与被扫描的策略总数,并说明分析覆盖了哪些权限维度。没有分母的「已扫描」无法判断覆盖程度。同时应区分「策略允许」与「实际可达」——两者之间还隔着网络路径、身份链与资源标签,只算前者会同时产生虚警与漏报。
与本块第十八条《规范错位》在这里以最实际的形式出现:策略分析能精确回答「这份配置允许什么」,却回答不了「这份配置是否符合当初的意图」。当组织把机器判定的结果当成合规结论时,被验证的其实是自己写下的规则,而不是自己想要的边界。
九、持续验证:证明必须随代码与依赖一起演化
形式化验证长期被想象成一次性工程:投入巨大人力证明一个版本,之后这份证明就作为资产存在。这个前提忽略了软件会持续演化——一次重构、一次依赖升级、甚至求解器换个版本,都可能让大批证明脚本失效。于是许多验证成果在项目结束后迅速腐化。这条转向把证明当作与代码同等的、需要持续维护的制品,纳入版本控制、回归测试与重构工具。
这条理论的可反驳命题是:证明脚本、规范与自动化也会发生脆化,应纳入版本控制、回归测试和重构工具。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“可重用证明义务数/版本变更义务总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。
主证据来自Ringer 等,2019年《Foundations and Trends in Programming Languages》5(1–2):1–218。具体设计与读数是:大规模证明工程复盘把库升级、自动化脆化、接口重构和证明性能列为持续成本;证明仓库必须像代码仓库一样跑回归。Coq、Isabelle、Dafny与Lean大型项目在2016年后的维护经验显示,库升级可触发广泛证明修复;模块化接口和自动化稳定性决定长期成本。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“求解器结果能否由小内核复查”。对照证据见Nguyen、Hoque、Bak、Drager与Johnson,2018年《ACM Transactions on Cyber-Physical Systems》2(4):23:1–23:26:论文在降压变换器和汽车空燃比控制两个案例中发现“软件不变量”与物理要求不等价;同一控制器参数下,输出电压区间可跨出给定容差,说明证明对象写错时,程序正确也不等于系统要求正确。它显示自动化提示会制造看似完整的证明脚本;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:报告版本变更后有多少证明义务可以复用、多少需要重证,以及重证所花的人力。这个比例决定了验证方案是否可持续,比首次证明的规模更能说明工程可行性。同时应把证明脚本的构建纳入持续集成,让证明失效像编译失败一样立即可见,而不是在半年后被发现。
与本块第一条《SMT求解器》之间存在一处容易被忽略的耦合:自动化程度越高,证明脚本对求解器版本与启发式的依赖就越隐蔽,升级一次工具链可能让大批原本通过的证明超时。自动化省下的人力,有一部分是以未来的脆化为代价预支的,这笔账要记在同一本上。
十、规范错位:被证明的程序仍可能做错事
形式化验证的结论常被当作绝对断言来传播:「这个系统已被证明正确」。这个说法省略了三个限定词——相对于哪份规范、哪个环境模型、哪一层抽象。规范写错时,证明会忠实地把错误结论证成定理;环境模型漏掉一种输入时,实际系统会在证明覆盖之外运行。这条转向把这些限定词提到台前,主张任何证明结论都只在其规范与模型的边界内成立,边界本身必须与结论一同交付。
这条理论的可反驳命题是:任何结论都只相对于规范、环境模型与抽象层成立;最危险的缺口常是需求没有被形式化。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“规范覆盖的业务意图条款数/业务条款总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。
主证据来自Nguyen、Hoque、Bak、Drager与Johnson,2018年《ACM Transactions on Cyber-Physical Systems》2(4):23:1–23:26。具体设计与读数是:论文在降压变换器和汽车空燃比控制两个案例中发现“软件不变量”与物理要求不等价;同一控制器参数下,输出电压区间可跨出给定容差,说明证明对象写错时,程序正确也不等于系统要求正确。seL4、CompCert与工业协议验证的复盘都把规范遗漏、设备模型和外部组件列为残余风险;证明范围说明逐渐成为交付物。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“抽象是否漏掉关键并发交错”。对照证据见Klein 等,2009年《SOSP会议录》:207–220,页207–220:团队证明约8700行C内核的所有执行细化抽象规范,证明脚本约二十万行Isabelle,工程投入约二十人年;规模本身成为可核对读数。它显示证明可能只对错误规范成立;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:交结论时一并交规范与环境模型,并说明业务意图中有多少条款被规范覆盖。规范评审因此成为独立工序,且必须由懂业务而不只是懂逻辑的人参与。相应地,验证报告要留出「已知未覆盖」一节——写不出这一节,通常说明还没有认真找过边界。
与本块第十二条《神经网络验证》和第十六条《云策略自动推理》一起构成同一个警告的三种形态:数学上越严格的结论,越容易被当成关于真实世界的结论。三条放在一起读,可以看出形式化方法真正的稀缺资源不是求解能力,而是把人的意图写成可检查规范的能力。
十一、可信基记账:证明强度应按未证明部分计价
验证成果的比较长期缺少共同分母:一个项目说证明了内核,另一个说验证了编译器,第三个说做了模型检查,彼此的强度无法对齐。默认的读法是按被证明的代码量排序。这条转向换了个分母——真正决定保证强度的不是证明了多少,而是还剩多少东西必须无条件相信:证明内核、逻辑一致性、公理、编译器、硬件模型与人工生成的步骤,都应逐项列出并计价。
这条理论的可反驳命题是:应公开列出内核、逻辑、公理、编译器、硬件与人工生成步骤,比较的是可信基大小与可审计性。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“已证明代码行/可信基代码行”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。它改写的不是工具名称,而是什么比较才算同一个问题。
主证据来自Gu 等,2016年《OSDI会议录》,USENIX。具体设计与读数是:CertiKOS把约6500行C与汇编实现连接到约六十五万行Coq证明;未建模的硬件、引导代码和定理证明器内核被明确列入可信基账本。2016年后proof-producing tools、verified boot chains和小内核路线反复采用TCB清单;同一‘已验证’标签可对应截然不同的剩余假设。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“端到端证明是否仍依赖未验证工具链”。对照证据见Leroy,2009年《Communications of the ACM》52(7):107–115:CompCert为主要编译阶段给出语义保持证明;后续Csmith随机测试在GCC和LLVM中发现数百个错误,而CompCert已验证核心没有出现同类错误代码。它显示可组合逻辑的工程成本可能超过缺陷风险;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:公开可信基清单,并给出已证明代码行与可信基代码行的比值。没有这份清单,两份「已验证」的成果无法比较,也无法判断某一次工具链变更是否扩大了可信基。这项要求同时改变了工程选择——有时缩小可信基比多证明几个模块更能提高实际保证。
与本块第六条《微内核全功能正确性》和第十四条《语言实现端到端证明》构成互补的三角:两者努力把证明边界往外推,本条负责为边界之外的部分明码标价。三条一起才回答得了「这份保证到底值多少」;只做前两条时,最常见的传播失真是把逐层细化的内核证明说成整机可信。
十二、机器建议、内核裁决:生成式证明不等于接受式证明
证明自动化的传统路线是把人的策略写成程序:策略语言、启发式、决策过程,都是把专家经验固化下来。随着模型能够生成引理、策略甚至完整证明脚本,一个新的默认开始出现——把生成的证明当作证明。这条转向拒绝了这个默认,主张搜索与裁决必须分开:模型可以负责提出,但接受与否只由小型证明内核判定,生成能力的提高不改变可信度的来源。
这条理论的可反驳命题是:模型可负责搜索引理与策略,但最终产物必须由小型证明内核重新检查。比较必须固定规范、依赖版本、输入域与可信基边界,只改变抽象、类型、不变量或证明证书,并以反例、覆盖性质、证明时间和未证明部分为共同结果;量纲写成“内核接受的证明建议数/机器生成建议总数”。若同等预算下不优于强基线,或换数据、平台与人群便失效,命题只能收窄。
主证据来自Yang 等,2023年《Advances in Neural Information Processing Systems》36:21573–21612。具体设计与读数是:LeanDojo从Mathlib抽取近十万条定理与证明轨迹供模型检索,但每个候选证明仍必须由Lean内核逐步接受;生成成功率与逻辑正确性被分成两道读数。2023年后的LeanDojo等把语言模型接入定理证明搜索,2024年前后多种系统提高自动解题率;幻觉不会穿过内核,却会增加搜索、依赖与规范选择。这笔证据把规范缺口、可信基、环境假设和状态爆炸从背景变量改成可复算的中间量,并留下样本、版本、阈值或预算检查点。主证据年份决定幕归属;核验应以篇名反查作者、卷页或DOI以及这里采用的读数。
争议集中在“学习组件的连续输入域能否被有限覆盖”。对照证据见Ospanov、Farnia与Yousefzadeh,2025年《NeurIPS 2025》:系统在Lean内核裁决下生成、检索和修复证明;miniF2F共488题、测试集244题,结果显示采样建议只有经过内核接受才成为证明,而非以自然语言流畅度代替正确性。它显示工业系统持续变化会使证明迅速过期;换任务、分母或组织流程后,成本可能转移到未记录处。争论要收敛,须预注册口径、公开负结果并由独立站点重做,同时报告均值、尾部、失败类型与维护成本。
它改变的最低交付责任是:报告内核接受的建议数与机器生成的建议总数,而不是只展示成功案例。接受率是这条路线的真实读数,也是与人工证明比较成本的唯一共同分母。同时要说明模型是否接触过目标定理的已有证明,否则成绩里混着记忆而不是搜索。
与本块第十五条《可检查证明证书》同源而风险不同:证书复查覆盖的是推理步骤,而模型生成的产物里,规范与定理陈述本身也可能被悄悄改写——内核会忠实地通过一个被削弱的定理。因此这条路线需要一道额外的检查:定理陈述必须由人或独立工具锁定,只有证明过程才交给机器搜索。
◎ 二十年连起来看
第一幕把验证从手工推导推进到共享求解器、可组合分析与工业级端到端案例。 第二幕不再只问“能否证明”,而是追问证明覆盖什么、遗漏什么、谁来复查以及如何持续更新。 两幕不是工具换代,而是评价单位不断扩大:第一幕找出局部上界、误差、约束或行为机制,第二幕把它们放进真实系统、组织与生命周期。只有当旧默认被写成可检查条件,新方法才构成转向。
被继承的是可检查证据链:SMT、证明证书、验证编译器和可信基记账都要求结论能回到较小的核验核心。 这一判据在二十条里反复出现:条件、操作、读数与边界必须形成可复查链条。工具名可以变化,数据来源、分母、中止、未达阈值或无法归类的对象和复现路径却不能省;这也是碰撞行能够抽取并与别的领域通约的基础。
被推翻的是“形式化等于全系统绝对正确”;两幕都未解决的是规范本身如何接受经验、用户和组织层面的反证。 因而,本领域尚未解决的核心不是再提高一个百分点,而是如何让证明随代码演化而不把规范审查与可信基记账重新藏回人工流程。若未来五年的工作仍只给均值和排行榜,不给真实部署、尾部和反例,它不会继续这条二十年主线。
◎ 三个常见误解
误解一:通过证明就不会出事故。它容易被相信,是因为单次榜单只显示结果而隐藏规范、依赖版本、输入域与可信基边界、中止、未达阈值或无法归类的对象与选择过程。正确表述是把收益限定在同一分母和同一边界内,再看是否跨环境保持。
误解二:类型系统只是文档。它容易被相信,是因为工具把一部分依赖封装起来,看上去像整个系统已经被封装。正确表述是任何抽象都只覆盖一段链条,外部数据、版本、组织和硬件仍需单独核验。
误解三:生成式证明器可以替代证明内核。它容易被相信,是因为成功案例适合传播,而可组合逻辑的工程成本可能超过缺陷风险通常不进入摘要。正确表述是收益与边界、代价、反例必须同时报告,不能把局部改进外推成普遍保证。
◎ 与相邻领域的接口
与〈软件安全与隐私工程〉的接口在于:可信基、密码实现与权限策略把证明边界直接接到威胁模型。 分工判据是,本块负责把计算对象、系统行为与可核对读数写清;相邻领域负责它自己的机制、制度或物理约束。若同一现象使用不同术语和分母,两边都保留,并在碰撞行登记异名。
与〈嵌入式与实时系统〉的接口在于:安全关键系统需要把离线证明与运行时保障壳接起来。 分工判据是,本块负责把计算对象、系统行为与可核对读数写清;相邻领域负责它自己的机制、制度或物理约束。若同一现象使用不同术语和分母,两边都保留,并在碰撞行登记异名。
与〈多智能体系统〉的接口在于:协议承诺和代理编排只有转成可执行状态机才可系统验证。 分工判据是,本块负责把计算对象、系统行为与可核对读数写清;相邻领域负责它自己的机制、制度或物理约束。若同一现象使用不同术语和分母,两边都保留,并在碰撞行登记异名。
与〈系统工程与管理科学〉的接口在于:系统级验证与确认关注“造对了系统”和“造了对的系统”的区分。 分工判据是,本块负责把计算对象、系统行为与可核对读数写清;相邻领域负责它自己的机制、制度或物理约束。若同一现象使用不同术语和分母,两边都保留,并在碰撞行登记异名。
◎ 争议现场
未收敛的争论是:轻量类型是否比深证明更有总体收益。支持方强调已有正向设计,反对方指出分母、样本或环境不足以外推。要怎样才能收敛:用不少于三个独立平台或人群,预注册共同基线、预算和停止规则,并以反例、覆盖性质、证明时间和未证明部分的分层分布比较;若方向一致且边界可预测,争论才收敛。
未收敛的争论是:机器学习组件应证明鲁棒半径还是系统风险界。支持方强调已有正向设计,反对方指出分母、样本或环境不足以外推。要怎样才能收敛:建立版本化公开基准,保存失败配置、调参轨迹和维护成本,以盲评方式复跑;若收益只在事后选择的路径上出现,应判为未收敛。
未收敛的争论是:可信基应按代码行、复杂度还是攻击面计价。支持方强调已有正向设计,反对方指出分母、样本或环境不足以外推。要怎样才能收敛:把局部结果接入真实工作流或制度现场,连续观测至少一个完整周期,并报告最差分位与反事实对照;只有端到端读数同向,才能排除成本转移。
◎ 往下五年看什么
观察点是持续集成中证明失败的平均修复时间。应固定统计周期、样本覆盖与质量门槛,按年度公布分布而非只公布最好值;若连续两次独立复测方向相反,就说明该读数尚不足以承担领域判据。
观察点是每项结论对应的可信基代码量与外部假设数。应固定统计周期、样本覆盖与质量门槛,按年度公布分布而非只公布最好值;若连续两次独立复测方向相反,就说明该读数尚不足以承担领域判据。
观察点是规范变更后可复用证明比例。应固定统计周期、样本覆盖与质量门槛,按年度公布分布而非只公布最好值;若连续两次独立复测方向相反,就说明该读数尚不足以承担领域判据。
观察点是生成式建议被证明内核拒绝的类型与频率。应固定统计周期、样本覆盖与质量门槛,按年度公布分布而非只公布最好值;若连续两次独立复测方向相反,就说明该读数尚不足以承担领域判据。
◎ 可与哪些领域对撞
本块第19条《可信基记账:证明强度应按未证明部分计价》与第354号第十三条《供应链谱系》可以对撞。它们共享的预设是:两边都默认可信结论取决于一条可追踪的生成链。相反点在于:可信基记账把未证明代码显式列出,供应链谱系把未验证制品和构建步骤列出。若两边都成立,若两边都成立,正确性必须按整条证据链中最弱且不可复查的一环计价。
本块第18条《规范错位:被证明的程序仍可能做错事》与第172号第02条《语境完整性》可以对撞。它们共享的预设是:两边都默认规则只有在其适用语境内才有意义。相反点在于:规范错位说明形式上满足规格仍可能做错事,语境完整性说明信息流合法与否取决于角色和传输原则。若两边都成立,若两边都成立,第三项就是规范必须携带情境参数而不能脱离使用关系。
本块第10条《验证密码软件:数学算法正确不等于实现安全》与第149号第一幕甲条《公允价值会计:信使还是加速器》可以对撞。它们共享的预设是:两边都默认测量或证明程序与被评价对象可以区分。相反点在于:规范错位追问“证明了什么”,公允价值争论追问“报告坏消息还是制造坏结果”。若两边都成立,若两边都成立,就要另外审查测量制度是否回写系统行为。
本块第17条《持续验证:证明必须随代码与依赖一起演化》与第074号第一幕己条《复制危机把注意力引向自由度》可以对撞。它们共享的预设是:两边都默认一次通过的结果会在环境和版本变化后继续成立。相反点在于:持续验证要求每次改动重放证明,复制危机要求锁定分析自由度并重做结论。若两边都成立,若两边都成立,第三项就是证据具有版本半衰期,必须设定重新核验触发条件。
◎ 十条可做的研究命题
性质导向可达性的因果识别命题:在控制共同预算后,IC3/PDR直接学习阻止坏状态的归纳子句,以性质为中心构造不变量;怎么做:在真实部署中随机或准随机改变抽象、类型、不变量或证明证书,固定规范、依赖版本、输入域与可信基边界,比较前后与未处理组;什么算证伪:若效应低于测量误差、跨环境方向不一致,或规范是否写出了真正业务意图不再预测失败,则命题被证伪。
精化类型的测量命题:在控制共同预算后,把逻辑谓词嵌入类型并交给自动求解器,可在接近普通编程的工作流中验证数组;怎么做:建立跨三种环境的统一日志,直接测量“由类型检查阻止的违规路径数/总潜在路径数”并分层报告尾部;什么算证伪:若效应低于测量误差、跨环境方向不一致,或求解器结果能否由小内核复查不再预测失败,则命题被证伪。
微内核全功能正确性的复现重估命题:在控制共同预算后,通过抽象规范、可执行实现与机器级模型的逐层细化,可证明真实微内核所有执行;怎么做:用新版本、强基线和独立团队重做第5条的关键设计,保存全部失败路径;什么算证伪:若效应低于测量误差、跨环境方向不一致,或抽象是否漏掉关键并发交错不再预测失败,则命题被证伪。
分布式系统机器证明的跨领域命题:在控制共同预算后,真实分布式实现应同时证明状态不变量、安全性、终止或活性,并把消息与故障模型;怎么做:把相邻领域的审计、因果或能量账本移入本领域,以共同分母连接反例、覆盖性质、证明时间和未证明部分;什么算证伪:若效应低于测量误差、跨环境方向不一致,或端到端证明是否仍依赖未验证工具链不再预测失败,则命题被证伪。
验证密码软件的因果识别命题:在控制共同预算后,实现必须把功能正确、内存安全、常数时间与编译链边界一并验证;怎么做:在真实部署中随机或准随机改变抽象、类型、不变量或证明证书,固定规范、依赖版本、输入域与可信基边界,比较前后与未处理组;什么算证伪:若效应低于测量误差、跨环境方向不一致,或学习组件的连续输入域能否被有限覆盖不再预测失败,则命题被证伪。
神经网络验证的测量命题:在控制共同预算后,对给定扰动集合和输出性质,可用线性松弛、分支定界或SMT检验是否存在对抗反例;怎么做:建立跨三种环境的统一日志,直接测量“已验证输入区域体积/允许输入域体积”并分层报告尾部;什么算证伪:若效应低于测量误差、跨环境方向不一致,或规范是否写出了真正业务意图不再预测失败,则命题被证伪。
语言实现端到端证明的复现重估命题:在控制共同预算后,可信语言栈应把源语义、编译器、运行时与机器执行连接成连续证明链;怎么做:用新版本、强基线和独立团队重做第13条的关键设计,保存全部失败路径;什么算证伪:若效应低于测量误差、跨环境方向不一致,或求解器结果能否由小内核复查不再预测失败,则命题被证伪。
云策略自动推理的跨领域命题:在控制共同预算后,策略应有形式语义,可自动回答可达权限、冲突与等价性问题;怎么做:把相邻领域的审计、因果或能量账本移入本领域,以共同分母连接反例、覆盖性质、证明时间和未证明部分;什么算证伪:若效应低于测量误差、跨环境方向不一致,或抽象是否漏掉关键并发交错不再预测失败,则命题被证伪。
规范错位的因果识别命题:在控制共同预算后,任何结论都只相对于规范、环境模型与抽象层成立;怎么做:在真实部署中随机或准随机改变抽象、类型、不变量或证明证书,固定规范、依赖版本、输入域与可信基边界,比较前后与未处理组;什么算证伪:若效应低于测量误差、跨环境方向不一致,或端到端证明是否仍依赖未验证工具链不再预测失败,则命题被证伪。
机器建议、内核裁决的测量命题:在控制共同预算后,模型可负责搜索引理与策略,但最终产物必须由小型证明内核重新检查;怎么做:建立跨三种环境的统一日志,直接测量“内核接受的证明建议数/机器生成建议总数”并分层报告尾部;什么算证伪:若效应低于测量误差、跨环境方向不一致,或学习组件的连续输入域能否被有限覆盖不再预测失败,则命题被证伪。
◎ 资料核验
- de Moura, L., & Bjørner, N. (2008). Z3: An efficient SMT solver. Proceedings of TACAS 2008, LNCS 4963, 337–340. Springer.
- Bradley, A. R. (2011). SAT-based model checking without unrolling. Proceedings of VMCAI 2011, LNCS 6538, 70–87. Springer.
- Calcagno, C., Distefano, D., O’Hearn, P. W., & Yang, H. (2009). Compositional shape analysis by means of bi-abduction. Proceedings of POPL 2009, 289–300. ACM.
- Rondon, P. M., Kawaguchi, M., & Jhala, R. (2008). Liquid types. Proceedings of PLDI 2008, 159–169. ACM.
- Leroy, X. (2009). Formal verification of a realistic compiler. Communications of the ACM, 52(7), 107–115.
- Klein, G., et al. (2009). seL4: Formal verification of an OS kernel. Proceedings of SOSP 2009, 207–220. ACM.
- Lopes, N. P., et al. (2015). Alive: Automatic verification of LLVM optimizations. Proceedings of PLDI 2015. ACM.
- Hawblitzel, C., et al. (2015). IronFleet: Proving practical distributed systems correct. Proceedings of SOSP 2015, 1–17. ACM.
- Jung, R., Krebbers, R., Jourdan, J.-H., Bizjak, A., Birkedal, L., & Dreyer, D. (2018). Iris from the ground up: A modular foundation for higher-order concurrent separation logic. Journal of Functional Programming, 28, e20. https://doi.org/10.1017/S0956796818000151.
- Zinzindohoué, J. K., Bhargavan, K., Protzenko, J., & Beurdouche, B. (2017). HACL*: A verified modern cryptographic library. Proceedings of CCS 2017, 1205–1222. ACM.
- CHC-COMP Organizers. (2018–2024). Competition reports for constrained Horn clause solving. HCVS Workshop.
- Katz, G., et al. (2017). Reluplex: An efficient SMT solver for verifying deep neural networks. Proceedings of CAV 2017, LNCS 10426, 97–117. Springer.
- Finkbeiner, B., Hahn, C., Stenger, M., & Tentrup, L. (2017). Monitoring hyperproperties. Proceedings of Runtime Verification 2017, LNCS 10548, 190–207. Springer.
- Tan, Y. K., et al. (2019). The verified CakeML compiler backend. Journal of Functional Programming, 29, e2.
- Cruz-Filipe, L., et al. (2017). Efficient certified RAT verification. Proceedings of CADE-26, LNCS 10395, 220–236. Springer.
- Cutler, J. W., et al. (2024). Cedar: A new language for expressive, fast, safe, and analyzable authorization. Proceedings of the ACM on Programming Languages, 8(OOPSLA1), 670–697.
- Ringer, T., et al. (2019). QED at large: A survey of engineering of formally verified software. Foundations and Trends in Programming Languages, 5(1–2), 1–218.
- Nguyen, L. V., Hoque, K. A., Bak, S., Drager, S., & Johnson, T. T. (2018). Cyber-physical specification mismatches. ACM Transactions on Cyber-Physical Systems, 2(4), Article 23, 1–26. https://doi.org/10.1145/3170500.
- Gu, R., et al. (2016). CertiKOS: An extensible architecture for building certified concurrent OS kernels. Proceedings of OSDI 2016. USENIX.
- Yang, K., et al. (2023). LeanDojo: Theorem proving with retrieval-augmented language models. Advances in Neural Information Processing Systems, 36, 21573–21612.
- Ospanov, A., Farnia, F., & Yousefzadeh, R. (2025). APOLLO: Automated LLM and Lean collaboration for advanced formal reasoning. Advances in Neural Information Processing Systems 38.