Page 152 - 《软件学报》2021年第6期
P. 152

1726                                     Journal of Software  软件学报 Vol.32, No.6,  June 2021

         调用为对同一合约内部函数的调用或对其他合约的外部调用,调用栈的变化情况分别如 B→C 和 B→F 所示.若
         为内部调用(B→C),则形成新的局部栈帧 lfrm″,并在原局部栈帧的代码部分中用形如 ERetId(_,_)的返回值占位
         符替换表达式 EImFunCall  f  es,形成局部栈帧 lfrm′.被调函数可正常执行后返回,弹出局部栈帧 lfrm″,并使用返
         回值替换 ERetId(_,_),形成局部栈帧 lfrm′ (C→D);被调函数亦可由于 gas 耗尽等原因抛出异常,从而销毁整个全
                                         1
         局栈帧〈lfrm″#lfrm′#lstk,…〉 N ,并代之以表示异常的全局栈帧〈…〉 E (C→E).直观上,后一种情况表示当前合约中所
         有的内部调用均异常终止.若表达式 EImFunCall  f  es 进行外部合约调用(即 f 为某个实现外部调用的内置函数
         的标识符),则形成新的全局栈帧 gfrm,并在原局部栈帧 lfrm′ 中用形如 ERetId(_,_)的返回值占位符替换表达式
                                                        0
         EImFunCall f es,形成局部栈帧 lfrm′′ (B→F).被调合约可正常终止于形如〈…〉 H 的全局栈帧(如图 1(G)所示),并向
                                     0
         调用者返回 1;被调合约亦可异常终止于形如〈…〉 E 的全局栈帧(如图 1(I)所示),并向调用者返回 0.





















                        Fig.1    Changes of the semantic configuration with function calls and returns
                                      图 1   函数调用和返回相关状态变化

             以下说明函数调用和返回所涉及的关键语义规则.函数调用表达式 EFunCall f es 的第 1 步执行如下.
             1.   step tre ([〈(EFunCall f es,ls,fs) E #lstk′,gs,ck〉 N ])=(
             2.      if (f∉lm_dom builtin_ctx)∧(valid (gas gs) 3 (ct gs))
             3.      then (let gs′=gs (| gas:=(gas gs)−3 |)
             4.         in [〈(EImFunCall f es,ls,fs) E #lstk′,gs′,ck〉 N ])
             5.      else (if (f∈lm_dom builtin_ctx) then ([〈(EImFunCall f es,ls,fs) E #lstk′,gs,ck〉 N ]) else [〈ck〉 E ])
             6.   )
             为了对 gas 消耗量进行描述,EFunCall f es 首先转化为中间表达式 EImFunCall f es.自定义函数调用和内置
         函数调用在 gas 消耗方面存在差异.当判断该语句是自定义函数调用时,该步执行需要消耗 3 个单位的 gas 值(第
         3 行);当判断该语句为内置函数的调用时,则该步执行无需消耗 gas(第 5 行 then 中的部分).
             中间表达式 EImFunCall f es 的语义规则如下所示.
             1.   step tre [〈(EImFunCall f es,ls,fs) E #lstk′,gs,ck〉 N ]=(
             2.   let (idx,found)=lst_find_idx(rev es) not_lit in (
             3.      if found then (
             4.         step_ctx tre (es!(|es-idx-1|)) (ECFunCall f(take|es-idx-1| es) Hole (map peel(drop|es-idx|es)))
             5.            [〈(EStop,ls,fs) E #lstk′,gs,ck〉 N ]
             6.   ) else (
             7.      case lm_get((aggr_fs((EImFunCall f es,ls,fs) E #lstk′))@builtin_ctx) f of
             8.         Some (FunctionV f ptl rtl blk)⇒(…
   147   148   149   150   151   152   153   154   155   156   157