Page 102 - 《软件学报》2025年第9期
P. 102

王小兵 等: Solidity  到  MSVL  转换的等价性研究                                              4013


                    Solidity  基本语句定义为   stmt, 包含语句块   stmt , 表达式语句  e;, 变量声明语句   VarDe f , 返回语句  return, 条件
                                                        ∗
                 判断语句   if-else, 循环语句, 转向语句   throw. 语法定义如下:

                                              ∗
                                    stmt::= {stmt }|e;|VarDe f|return e;|return;|if (e) stmt 1 (else stmt 2 )?

                                          |for(stmt 1 ;e; stmt 2 ) stmt|while(e) stmt|throw;

                 2.2   语义定义策略
                    本节在定义     Solidity  操作语义时, 首先借鉴了文献     [20] 中  Solidity  语义定义的基本形式, 其中给出的大步语义
                 形式的   Solidity  求值规则与核心动态语义为本文提供了基础结构, 并且对于以太坊状态和                     Solidity  状态的形式化
                 定义也为本文定义语义元素提供了思路. 之后参考了文献                    [21] 中对于  Solidity  内存模型的研究, 其中给出的对
                 Solidity  内存模型以及函数调用的形式化定义, 为本文定义语义元素中的内存模块提供了理论基础, 也为函数调用
                 的操作语义提供了值得借鉴的步骤. 然后参考文献                [18] 中证明  C  语言与  MSVL  操作语义等价性的方法, 确定了本
                 文的等价性证明思路. 针对将来          Solidity  快速迭代引入的新版本特性, 可根据语句变化完善现有的操作语义, 进而
                 将本文的等价性研究工作扩展到           Solidity  高阶版本.
                    本节所定义的      Solidity  操作语义覆盖了  Solidity  的主要语法, 并给出了更详尽的语义元素以及操作函数定义,
                 相较于文献    [20] 的  Solidity  操作语义更加完善. 本文采用大步语义的形式定义          Solidity  的操作语义, 这一方面是由
                 于文献   [18] 均采用大步语义的形式, 保持形式的一致有利于之后等价性的证明以及研究的扩展; 另一方面大步语
                 义在描述高级程序设计语言的操作语义上更有优势. 小步语义通常用于描述机器级语言的语义, 更注重于描述程
                 序每走一步的规则, 解释执行语句的每个步骤如何进行, 即将父结构不断拆分为子结构, 最终递归得到结果; 而大
                 步语义则更关注程序的开始与结束的状态变化, 描述如何得到语句执行终止的最终状态, 预设了语句可终止, 所给
                 出的操作语义更加高效, 易于调试和扩展            [22] .
                    大步语义的求值规则有如下基本形式             [23] :

                                                         ρ ⊢ e ⇒ v                                    (1)

                                                                                                      (2)
                                                        s 1 ⊢ e ⇒ s 2
                 其中,  ρ 为环境, 公式  (1) 表示在环境   ρ 中表达式   e 的值为  .     s 2  为状态, 公式  (2) 表示在状态   s 1  下执行表达式  e
                                                             v s 1  与
                            s 2 . 基于此本文定义了   Solidity  的求值规则.
                 会得到新状态
                    语义的推导规则通常有如下形式:

                                                         P 1 P 2 ...P n
                                                                                                      (3)
                                                            C
                 其中,  P i (1 ⩽ i ⩽ n) 为假设或者前提,   C  表示结论, 若假设或前提   P i  均成立, 则结论  C  一定成立, 若没有假设或前提,
                 结论依然成立, 那么结论即为公理.

                 2.3   内存模型
                    Solidity  与其他语言不同, 使用   memory、storage、callback  和  stack  这  4  个不同的数据位置, 其中  stack  只有在
                 为字节码赋予语义时才有研究意义, 而              calldata  位置的作用可以忽略, 因此本文中仅关注前两项              memory  和
                 storage 数据位置.
                    (1) memory: 存储函数内部的所有本地数据, 即局部变量. memory          数据在函数执行完成后被删除.
                    (2) storage: 存储函数外部的数据, 即状态变量. 在       storage 中的变量将永久保存在区块链上. storage 是一组存
                 储槽, 每个槽长    32  字节, 可通过  256  位地址寻址.
                    (3) callback: 存储函数的传入执行数据, 不可修改.
                    (4) stack: 用于加载变量和存储    EVM  生成的中间值.
                    Solidity  中状态变量可以是机器整数、地址、数组、结构体或者映射类型. 状态变量为                       storage 类型, 永久存
                 储在区块链中. 函数中的局部变量默认为             memory  类型, 也可显示声明为     storage 类型. 此外, 全局变量在   storage 中
                 的存储位置由数据类型决定, 其规则如下.
   97   98   99   100   101   102   103   104   105   106   107