之前已经提到过,交易有两种类型,一种是消息调用,使用 Θ 表示,合约创建其实就是创建账户的过程,账户是包含合约代码的账户。
(σ′,g′,A,z,o)≡Θ(σ,s,o,r,c,g,p,v,v~,d,e,w)
上面是完整的创建函数定义,输入参数定义如下:
- σ,执行前的状态,此状态是已经完成交易前操作的状态,即从发送方账户扣掉 TgTp,同时
nonce
加一了。
- s,发送方账户。
- o,原始的交易发起者。当合约创建和消息调用过程不是直接通过交易发起的而是由代码触发时会和发起者不同。
- r,接收方账户。
- c,被执行代码的账户,通常就是接收方账户。
- g,可用的 gas。
- p,gasprice。
- v,发送方给接收方得金额。
- v~,表示进行合约方法调用时的输入。
- d,消息调用的输入。
- e,此时的栈深度。
- w,代表对状态修改的权限。
输出之前介绍过前 4 个,第五个 o 为执行消息调用后的返回值,如果是调用合约即为代码执行的返回值,如果只是转账该值被忽略。
下面定义转账后的状态为 σ1,则有:
σ1[r]b≡σ[r]b+v ∧ σ1[s]b≡σ[s]b−v
如果接收方的账户不存在,则会创建一个账户,流程和创建合约账户类似:
σ1σ1[s]a1and σ1′a1′≡σ1′ except:≡{∅a1if σ1′[s]=∅ ∧v=0otherwise≡(σ1′[s]n,σ1′[s]b−v,σ1′[s]s,σ1′[s]c)≡σ except:⎩⎨⎧σ1′[r]≡(0,v,TRIE(∅),KEC(()))σ1′[r]≡∅σ1′[r]≡a1′if σ[r]=∅ ∧ v≠0if σ[r]=∅ ∧ v=0otherwise≡(σ[r]n,σ[r]b−v,σ[r]s,σ[r]c)
接着账户的代码会被执行 ( 就是账户 codeHash
对应的代码 )。和创建账户一样,如果出现异常,gas 不会返还,同时状态会直接会退到转账之前 (即 σ 状态)。
σ′g′z(σ⋆⋆,g⋆⋆,A,o)IaIoIpIdIsIvIeIwtLet KEC(Ib)≡{σσ⋆⋆if σ⋆⋆=∅otherwise≡{0g⋆⋆if σ⋆⋆=∅ ∧o=∅otherwise≡{01if σ⋆⋆=∅otherwise≡Ξ≡r≡o≡p≡d≡s≡v~≡e≡w≡{s,r}=σ[c]c
其中 Ξ 定义如下:
Ξ≡⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧ΞECREC(σ1,g,I,t)ΞSHA256(σ1,g,I,t)ΞRIP160(σ1,g,I,t)ΞID(σ1,g,I,t)ΞEXPMOD(σ1,g,I,t)ΞBNADD(σ1,g,I,t)ΞBNMUL(σ1,g,I,t)ΞZNARKV(σ1,g,I,t)Ξ(σ1,g,I,t)if r=1if r=2if r=3if r=4if r=5if r=6if r=7if r=8otherwise
前八个为以太坊预置得的智能合约。