一个交易数据中附加了合约创建代码或者合约函数调用代码,以太坊客户端就会相应的使用EVM来运行这些代码。所有智能合约代码最终反映为EVM机器码,以下是常有的EVM操作码.
POP PUSH MLOAD MSTORE JUMP PC MSIZE GAS DUP SWAP
CREATE CALL RETURN REVERT SELFDESTRUCT
ADD MUL SUB DIV SDIV MOD SMOD ADDMOD MULMOD EXP STOP
ADDRESS BALANCE CALLVALUE ORIGIN CALLER CODESIZE GASPRICE EXTCODESIZE RETURNDATACOPY
在EVM中,从逻辑上讲有两类程序代码
一类叫做“运行时字节码”,他们保存在ROM中,由各节点维护,且基于账户地址标识。
一类叫做“字节码”,仅在合约创建时执行一次,用来生成合约的“运行时字节码”的代码,不会持久化保存。
合约创建可以由一个外部用户签名的交易执行触发,也可以在合约代码中由特定的合约代码所触发。对于EVM中执行合约,他需要若干输入参数。
如果合约初始化代码的执行没有发生任何异常,那么由其所生成的合约“运行时字节码”会被保存到EVM的ROM中。此外还需要从发送者账号的balance中扣除执行这些初始化代码所消耗的gas费用和代码保存费用。
如果合约初始化代码的执行发生异常,那么将不会创建任何账户和任何金额转移。
与合约创建一样,可以由一个外部用户签名的交易执行触发,也可以在合约代码中由特定的合约代码所触发。对于在EVM执行消息调用而言,也需要执行若干输入数据。
在EVM中有4个操作码可以发起消息调用。
| 操作码 | 说明 |
| CALL | 向某个接受者发起消息调用,recipient与sender可以相同,也可以不同 |
| CALLCODE | 与CALL基本等价,但recipient与sender相同且与code address相同 |
| DELEGATECALL | 与CALL基本等价,但recipent与sender相同且与code address不同 |
| STATICCALL | 与CALL基本等级,但不允许转账,且不允许对状态进行任何修改 |
看看区块如何最终定稿并添加到区块链中。
ommer验证
要求ommer区块的父区块必须是当前区块6代(含)以内的祖先区块。
交易验证
对于生成区块的矿工而言,他需要从本地维护的交易池中选择哪些gasPrice合适的交易来顺序执行,同时更改相应的状态和存储并生成交易收据数据。
对于非矿工全节点而言,除了顺序执行所有交易,同时更改本地维护的状态树、存储树,生成交易收据,并计算累计的gas消耗量与区块头中给定的gasUsed相符。
奖励发放
前期区块的beneficiary最多可获得1+2/32的基础区块奖励。
状态验证
对于生成区块的矿工而言,所有交易执行所导致的状态变动以及奖励发放之后的最终‘状态树’根节点哈希值保存到区块头的stateRoot字段。
对于非矿工全节点,则需要验证按区块中包含交易数据列表顺序执行完所有交易,并发放区块奖励之后的“状态树”根节点哈希值是否与区块头的stateRoot相符。
对于矿工节点,就是基于Ethhas算法获得nonce和mixHash的值
对于非矿工节点,就是验证区块头中保存的这两个数据的一致性。