使用了可变、可扩展的 memory 大小:固定 memory 的大小是不必要的限制,太小或太大都不合适。如果内存大小是固定的,每次访问内存都需要检查访问是否超出边界,显然这样的效率并不高。
1024 调用深度限制:许多编程语言在内存还没有溢出时,就因为调用深度太深而崩溃了。所以仅使用区块 gas 上限一种限制是不够的。
无类型:只是为了简洁。不过,DIV、SDIV、MOD、SMOD 会使用有符号(signed)或无符号的操作码(事实证明,对于操作码 ADD 和 MUL,有符号和无符号是对等的);转换成定点运算在所有情况下都很简单,例如,在 32 位长度下,a * b -> (a * b) / 2^32, a / b -> a * 2^32 / b ,+、- 和 * 在整数下不变。
校对注:在原译本中还有如下一段,但其对应段落在当前版本的原文中已经删除了: 栈大小没有限制:没什么特别理由!许多情况下,该设计不是绝对必要的;因为,gas 的开销和区块 gas 上限总是会充当每种资源消耗的上限。
这个 VM 中某些操作码的功能和用意很容易理解,但也有一些不太好理解,以下是一些特殊的原因:
ADDMOD, MULMOD:大多数情况下, mulmod(a, b, c) = a * b % c ,但在椭圆曲线算法中,使用的是 32 字节模数运算,直接执行 a * b % c 实际上是在执行 ((a * b) % 2^256) % c ,会得到完全不同的结果。在 32 字节的空间中执行 32 字节数值的 a * b % c 计算的共识非常困难且繁琐。
SIGNEXTEND:SIGNEXTEND操作码的作用是为了方便从大的有符号整数到小的有符号整数的类型转换。小的有符号整数是很有用的,因为未来的即时编译虚拟机也许有能力检测主要处理 32 字节整数又长时间运行的代码块,小的有符号整数能加快处理。
SHA3:在以太坊代码中,SHA3 作为安全的、高强度的、不定长数据哈希映射方法,应用非常广泛。通常,在使用存储器时,需要使用 Hash 函数来防止恶意冲突,在验证默克尔树和类似的以太坊数据结构时也需要使用到 Hash 函数。重要的是,与 SHA3 的相似的哈希函数,如 SHA256、ECRECVOR、RIPEM160,不是以操作码的形式包含在里面,而是以伪合约的形式。这样做的目的是将它们放在一个单独的类别中,如果当我们以后提出适当的 “原生插件” 系统时,可以添加更多这样的合约,而不需要扩展操作码。
ORIGIN:ORIGIN 操作码由交易的发送者提供,主要的作用是允许合约退回支付的 gas。
COINBASE:COINBASE 的主要作用是:1)允许子货币对网络安全作出贡献;2)使矿工能够作为一个去中心化的经济体,来设置基于子共识的应用,如 Schellingcoin。
PREVHASH:PREVHASH 可用作一个半安全的随机来源。此外,允许合约求值(evalute)上一个区块的默克尔树状态证明,而不需要高度复杂的 “以太坊轻客户端” 递归结构 。
(责任编辑:admin) |