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、内存和存储三个维度,模块图如下:

../../../_images/precompiled_gas.png

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.

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

Precompiled合约CPU、存储Gas计算

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

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

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

操作说明操作码
EQConditionPrecompiled的EQ调用,判断两个操作数是否相等0x00
GEConditionPrecompiled的GE调用,判读左值是否大于等于右值0x01
GTConditionPrecompiled的GT调用,判断左值是否大于右值0x02
LEConditionPrecompiled的LE调用,判断左值是否小于等于右值0x03
LTConditionPrecompiled的LT调用,判断左值是否小于右值0x04
NEConditionPrecompiled的NE调用,判断左值是否不等于右值0x05
LimitConditionPrecompiled的Limit调用,限制从CRUD接口中查询出来的数据条数0x06
GetIntEntryPrecompiled的getInt调用,将字符串转换成int256/uint256返回0x07
GetAddrEntryPrecompiled的getAddress调用,将字符串转换成Address0x08
SetEntryPrecompiled的set调用,设置指定Key的值为指定的Value0x09
GetByte32EntryPrecompiled的getByte32,将字符串转换为byte 320x0a
GetByte64EntryPrecompiled的getByte64,将字符串转换为byte 640x0b
GetStringEntryPrecompiled的getString,获取输入的Key对应的值Value0x0c
CreateTableTableFactoryPrecompiled的createTable调用,创建表0x0d
OpenTableTableFactoryPrecompiled的openTable调用,打开表0x0e
SelectTablePrecompiled的select调用,查询表0x0f
InsertTablePrecompiled的insert调用,向表中插入指定记录0x10
UpdateTablePrecompiled的update调用,更新指定表中的指定记录0x11
RemoveTablePrecompiled的remove调用,删除指定表中的指定记录0x12
PaillierAdd同态加接口0x13
GroupSigVerify群签名验证接口0x14
RingSigVerify环签名验证接口0x15
Precompiled合约基础操作衡量标准

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

操作Gas消耗
EQ3
GE3
GT3
LE3
LT3
NE3
Limit3
GetInt3
GetAddr3
Set3
GetByte323
GetByte643
GetString3
CreateTable16000
OpenTable200
Select200
Insert10000
Update10000
Remove2500
PaillierAdd20000
GroupSigVerify20000
RingSigVerify20000

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衡量模式,如下图所示:

../../../_images/free_storage.png

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

Gas衡量标准

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

EVM虚拟机Gas衡量标准

Gas说明EVMSchedule模式下Gas消耗FreeStorageEVMSchedule模式下Gas消耗
CreateGas创建合约的Gas消耗3200016000
sloadGas从存储读取32字节数据消耗的Gas2001200
sstoreSetGas添加32字节数据到存储的Gas消耗200001200
sstoreResetGas更新32字节存储数据的Gas消耗50001200

Precompiled合约Gas衡量标准

Gas说明GasMetrics模式下Gas消耗FreeStorageGasMetrics模式下Gas消耗
CreateTableGas创建表的Gas消耗16000500
StoreGas向表中插入数据或更新表中数据的Gas消耗10000200
RemoveGas删除表中数据的Gas消耗2500200

配置项

注解

EVM Gas衡量标准支持插件化配置项位于 genesis 文件中,详细可参考 这里