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

4014                                                       软件学报  2025  年第  36  卷第  9  期


                    (1) 值类型仅使用它们所需的字节, 若当前插槽的剩余空间不足以存放一个值类型, 则将其存放在下一个存储
                 插槽.
                    (2) 结构体与数组类型总是放在一个存储插槽的开始, 结构体与数组中的各元素按规则紧密存储.
                    (3) 映射与动态数组不可预知大小, 因此仅占用             32  字节, 其包含的元素存储的位置由         keccak-256  哈希函数计
                 算确定. 映射所占用的插槽实际上并未使用, 但仍需要. 动态数组所占用的插槽存放数组中元素的数量.
                    可知基本类型仅使用存储它们所需的字节, 结构体和数组等总是占用一整个新插槽, 因此                             storage 地址由插槽
                 索引值   sl 以及插槽内偏移量     δ 决定.

                 2.4   语义元素
                    本文定义    Solidity  状态  µ =< a,σ, M > 为一个三元组, 包含当前合约在区块链中的地址         address, 记为  a, 以太坊
                        σ 和内存   memory    M, memory  用于保存当前正在执行的函数的局部变量. 执行智能合约代码会改变
                 网络状态                 状态
                                                                                   a
                 以太坊网络的状态, 从形式化的角度来看, 以太坊网络状态                    σ  可由智能合约地址   映射得到, 定义网络状态
                                                                                 p, 以及存储               S ,
                 σ =< b, p,S > 为一个三元组, 包含合约余额      b, 即账户所持有的货币数量, 合约程序                    storage 的状态
                 storage 用于保存合约的状态变量.
                    表  6  为  Solidity  语义元素的定义, 其中左值  lv 表示变量在   storage 中或者  memory  中的地址,  sl 为  storage 插槽
                                                             δ
                 索引, storage 地址   addr  是一个由存储插槽索引与偏移量   组成的序偶对. 求值环境包括全局环境                  g 与局部环境   l.
                 fd  为函数定义, 全局环境    g 将程序全局变量和函数名映射到存储插槽索引, 若为函数, 则可以从索引映射到函数定
                 义局部环境. 局部环境      l 将局部变量映射到      memory  地址. 内存状态   M  从  memory  地址映射到其内容, 存储状态      S
                 从  storage 插槽索引映射到其内容.     τ 表示表达式所对应的类型.

                                                      表 6 语义元素

                    语义元素            定义                                    说明
                    左值  lv        lv ::= loc|addr  loc表示局部变量在memory中的地址,  addr 表示全局变量在storage中的地址
                 storage地址  addr  addr ::= (sl,δ)  storage插槽索引与偏移量组成的序偶对
                   全局环境   g   g ::= (id → sl)×(sl → fd) 从全局变量映射到storage插槽索引, 并从插槽索引映射到函数定义
                  函数局部环境    l     l ::= id → loc  从局部变量映射到memory地址, 函数局部环境     l 用于保存当前函数内部的局部变量
                 内存memory状态       M ::= loc → v  从memory地址映射到内容
                 存储storage状态       S ::= sl → v  从storage插槽索引映射到内容
                     类型  τ            τ e      表达式  e 的类型
                 结构体成员变量             λ id      结构体  id 的成员列表

                    表  7  给出了在存储    storage 状态、全局环境和局部环境上的操作. 在           storage 状态上有  store、 load、 delete、
                 alloc 这  4  个基本操作, 函数  store 在  storage 地址  addr  处存储类型为   的值  v. 函数  load  在  storage 地址  addr  处根
                                                                      τ
                 据内存长度加载其对应的内容. 函数           alloc 能够在  storage 地址  addr 处根据类型  τ 分配相应的存储长度. Solidity  的
                 storage 永久存储在区块链之上, 区块链作为一种公有资源, 为避免滥用, 鼓励使用者主动对空间进行回收, 释放空
                 间时会返还    gas, 但是  Solidity  中的  delete 与其他语言有所不同, 并非释放空间, 而是对变量进行初始化.
                                                                    ,
                    在全局环境上和局部环境上均有函数              getAddr  和函数  getSize getAddr  可以根据全局环境或局部环境以及变
                 量名称从   storage 或者  memory  中获取其映射的内容. 函数     getSize 可根据全局环境或局部环境以及当前变量的类
                 型, 获取其所需的内存长度.
                    表  8  给出了部分函数定义, 左值函数用于对地址的求值, 在左值表达式求值时给出具体应用, 其中, 函数
                 field_offset(id,φ) 根据结构成员列表  φ 进行查询, 得到名称为      id 的成员变量的偏移量. 函数       LVs_struct(s_id,addr,id)
                                                    id 在                                  addr 得到成员变量
                 首先根据函数     field_offset(id,φ) 得到成员变量     storage 中的偏移量, 再结合结构体的首地址
                 在  storage 中的实际位置. 函数   LVs_arr(le,addr,i) 首先根据数组类型   与索引值计算元组相对于数组首地址的偏
                                                                      τ
                                      addr, 得到成员变量在     storage 中的实际位置. 右值函数中给出了单目运算与双目运算
                 移量, 再结合数组的首地址
                 的函数. 布尔函数中根据变量的类型与值, 计算真值.
   98   99   100   101   102   103   104   105   106   107   108