Gas

标签:Gas 智能合约 虚拟机


EVM虚拟机有一整套Gas机制来衡量每笔交易上链消耗的CPU、内存和存储资源。FISCO BCOS 2.0引入了Precompiled合约,支持内置的C++合约,为了提升Precompiled合约的安全性,FISCO BCOS v2.4.0在Precompiled合约中引入了Gas机制。

此外,EVM原始的Gas机制中,交易的主要Gas消耗来源于存储,考虑到联盟链场景更关注CPU和内存消耗,FISCO BCOS v2.4.0调整了存储Gas,引入Free Storage Gas衡量模式,提升CPU和内存在交易Gas消耗中的占比。

Precompiled合约支持Gas计算

注解

Precompiled合约支持Gas计算的特性从v2.4.0开始支持,当 supported_version 小于v2.4.0,或者旧链直接替换二进制升级时,不支持该特性

模块架构

FISCO BCOS v2.4.0新增了PrecompiledGas模块进行Gas计算,Gas开销主要包括CPU、内存和存储三个维度,模块图如下:

PrecompiledGas主要记录了每个交易执行Precompiled合约过程中调用的基础操作、占用内存消耗的Gas,交易调用Precompiled合约时Gas计算机制如下:

  • 虚拟机执行交易调用Precompiled合约的call接口时,每调用一个基础操作,会将其对应的OPCode添加到PrecompiledGas运行时指令集合

  • 虚拟机执行交易调用Precompiled合约的call接口时,基础操作占用的内存变化时,会更新PrecompiledGas的运行时消耗的内存

  • Precompiled合约执行完毕后,可调用接口,根据运行Precompiled合约过程中执行的指令集合、消耗的内存,计算出该Precompiled合约Gas消耗。

Precompiled合约Gas衡量标准

FISCO BCOS Precompiled合约Gas衡量标准参考了EVM,主要包括CPU、内存和存储三个维度。下面详细介绍Precompiled合约具体的Gas计算方法。

Precompiled合约内存Gas计算

Precompiled合约内存消耗主要来自于输入、输出以及运行时产生的额外内存消耗。某笔交易消耗的总内存为txMemUsed时,其对应的内存Gas计算公式如下。即:每32字节增加memoryGasUnit个Gas,memoryGasUnit的值为3.

    MemoryGas(txMemUsed) = memoryGasUnit * txMemUsed / 32 + (txMemUsed * txMemUsed)/512

Precompiled合约CPU、存储Gas计算

为了计算Precompiled合约基础操作消耗的Gas,FISCO BCOS v2.4.0将Precompiled合约映射到具体的操作码,并定义了每个基础操作对应的Gas。

Precompiled合约基础操作对应的操作码

PrecompiledGas模块将Precompiled合约基础操作映射到了操作码如下:

操作

说明

操作码

EQ

ConditionPrecompiled的EQ调用,判断两个操作数是否相等

0x00

GE

ConditionPrecompiled的GE调用,判读左值是否大于等于右值

0x01

GT

ConditionPrecompiled的GT调用,判断左值是否大于右值

0x02

LE

ConditionPrecompiled的LE调用,判断左值是否小于等于右值

0x03

LT

ConditionPrecompiled的LT调用,判断左值是否小于右值

0x04

NE

ConditionPrecompiled的NE调用,判断左值是否不等于右值

0x05

Limit

ConditionPrecompiled的Limit调用,限制从CRUD接口中查询出来的数据条数

0x06

GetInt

EntryPrecompiled的getInt调用,将字符串转换成int256/uint256返回

0x07

GetAddr

EntryPrecompiled的getAddress调用,将字符串转换成Address

0x08

Set

EntryPrecompiled的set调用,设置指定Key的值为指定的Value

0x09

GetByte32

EntryPrecompiled的getByte32,将字符串转换为byte 32

0x0a

GetByte64

EntryPrecompiled的getByte64,将字符串转换为byte 64

0x0b

GetString

EntryPrecompiled的getString,获取输入的Key对应的值Value

0x0c

CreateTable

TableFactoryPrecompiled的createTable调用,创建表

0x0d

OpenTable

TableFactoryPrecompiled的openTable调用,打开表

0x0e

Select

TablePrecompiled的select调用,查询表

0x0f

Insert

TablePrecompiled的insert调用,向表中插入指定记录

0x10

Update

TablePrecompiled的update调用,更新指定表中的指定记录

0x11

Remove

TablePrecompiled的remove调用,删除指定表中的指定记录

0x12

PaillierAdd

同态加接口

0x13

GroupSigVerify

群签名验证接口

0x14

RingSigVerify

环签名验证接口

0x15

Precompiled合约基础操作衡量标准

PrecompiledGas定义了Precompiled合约每个基础操作对应的Gas消耗,具体如下:

操作 Gas消耗
EQ 3
GE 3
GT 3
LE 3
LT 3
NE 3
Limit 3
GetInt 3
GetAddr 3
Set 3
GetByte32 3
GetByte64 3
GetString 3
CreateTable 16000
OpenTable 200
Select 200
Insert 10000
Update 10000
Remove 2500
PaillierAdd 20000
GroupSigVerify 20000
RingSigVerify 20000

EVM Gas衡量标准插件化

如前面所述,针对部分场景衡量交易资源耗用时,更加关注CPU和Gas,FISCO BCOS v2.4.0引入了Free Storage的Gas衡量模式,提升CPU和内存在交易Gas消耗中的占比。

注解

EVM Gas衡量标准支持插件化配置的特性从v2.4.0开始支持,当 supported_version 小于v2.4.0,或者旧链直接替换二进制升级时,不支持该特性

模块架构

为了支持Gas衡量标准插件化配置和FreeStorage的Gas衡量模式,FISCO BCOS v2.4.0在以太坊EVMSchedule引入FreeStorageEVMSchedule,在PrecopmiledGas的GasMetrics基础上引入了FreeStorageGasMetrics,并根据genesis文件的enable_free_storage配置项决定启用哪种Gas衡量模式,如下图所示:

为了提升CPU和内存在交易Gas消耗中的占比,FreeStorageEVMSchedule调整了创建合约、SSTORESLOAD等操作的Gas消耗;FreeStorageGasMetrics主要调整了CreateTableInsertRemoveUpdate等操作的Gas消耗。

Gas衡量标准

下面分别介绍非FreeStorage模式和FreeStorage模式下,EVM虚拟机和Precompiled合约Gas衡量标准:

EVM虚拟机Gas衡量标准

Gas

说明

EVMSchedule模式下Gas消耗

FreeStorageEVMSchedule模式下Gas消耗

CreateGas

创建合约的Gas消耗

32000

16000

sloadGas

从存储读取32字节数据消耗的Gas

200

1200

sstoreSetGas

添加32字节数据到存储的Gas消耗

20000

1200

sstoreResetGas

更新32字节存储数据的Gas消耗

5000

1200

Precompiled合约Gas衡量标准

Gas

说明

GasMetrics模式下Gas消耗

FreeStorageGasMetrics模式下Gas消耗

CreateTableGas

创建表的Gas消耗

16000

500

StoreGas

向表中插入数据或更新表中数据的Gas消耗

10000

200

RemoveGas

删除表中数据的Gas消耗

2500

200

配置项

注解

EVM Gas衡量标准支持插件化配置项位于 ``genesis`文件中