字节验证码程序

字节码验证程序:用于检查堆栈使用、类型、资源及引用的安全性

编译后的模块中每个函数体分别进行单独验证,同时验证信任模块中函数签名的正确性。检查每个函数签名是否匹配其自定义内容,单独执行验证。函数体是一系列字节码指令。这个指令在下面描述的几个阶段中检查。

CFG构建

通过将指令集拆解为一组基本块,构造一个控制流程图。每个基本块包含一系列连续的指令; 所有指令集都存在于块中。每个块以分支或返回指令结束,块的分解可确保分支只在某个块的开头处,分解还试图确保生成的块是最大的。但是,分析的可靠性不依赖于最大化。

堆栈安全

块的执行发生在局部变量数组和堆栈中。函数的参数是局部变量数组的前缀。跨函数调用传递参数和返回值都是通过堆栈完成的。当函数开始执行时,其参数已经加载到其参数中。假设函数开始执行时堆栈高度为n;那么有效的字节码必须强制不执行,也就是执行开始,基本块的堆栈高度为n。此外,在返回指令处,堆栈高度必须是n + k,其中k,s.t。 k> = 0是返回值的数量。第一阶段通过分别分析每个块来检查是否保持了这个高度不变,计算块中每个指令对堆栈高度的影响,检查高度是否低于n,并且保留在n或n + k(取决于块的最终指令和函数的返回类型)。

类型安全

分析第二阶段检查是否使用原始函数或已定义函数的参数来调用每个操作。操作的操作数是位于局部变量或堆栈中的值。字节码中已经提供了函数的局部变量类型。 但是,需要堆栈值的类型。可以针对每个块单独地进行该推断和每个操作的类型检查。由于每个块开始时的堆栈高度为n并且在执行块期间不会低于n,因此我们只需要对从n开始的堆栈的后缀进行检查,以便对块指令进行类型检查。我们使用一堆类型对此后缀进行检查,在处理块中的指令流时,在这些类型上推送和返回类型。堆栈类型和静态已知类型的局部变量键入来检查每条指令。

资源安全

资源代表区块链上的资产。因此,对这些类型存在某些限制,这些限制不适用于正常值。直观地说,资源值无法复制,必须在交易结束时使用(这意味着到达全局存储或销毁)。具体而言,有以下限制:

l CopyLoc 和 StLoc 要求本地类型不是资源类型。

l WriteRef, Eq, 和 Neq 要求引用的类型不属于资源类型。

l 在函数结束时 (达到 Ret), 任何类型为资源类型的局部变量都不能为空,即该值必须已从本地移出。

如上所述,围绕 Ret 的最后一条规则意味着资源必须是:

l 通过 MoveToSender 移动到全局存储。

l 通过 Unpack 销毁。

MoveToSender 和 Unpack 都位于资源模块内部。

Last updated