以太坊GasLimit的计算方法

作者: swapmem | 来源:发表于2019-05-21 10:01 被阅读11次

静态Gas的计算

以太坊黄皮书上说的gasLimit的计算方法:

gasLimit = Gtransaction + Gtxdatanonzero × dataByteLength

需要注意的是这只是静态的gas消耗,实际gas消耗还需要加上合约执行的开销。

计算 IntrinsicGas的源码位置 core/state_transition.go

// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) {
    // Set the starting gas for the raw transaction
    var gas uint64
    if contractCreation && homestead {
        gas = params.TxGasContractCreation
    } else {
        gas = params.TxGas
    }
    // Bump the required gas by the amount of transactional data
    if len(data) > 0 {
        // Zero and non-zero bytes are priced differently
        var nz uint64
        for _, byt := range data {
            if byt != 0 {
                nz++
            }
        }
        // Make sure we don't exceed uint64 for all data combinations
        if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz {
            return 0, vm.ErrOutOfGas
        }
        gas += nz * params.TxDataNonZeroGas

        z := uint64(len(data)) - nz
        if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
            return 0, vm.ErrOutOfGas
        }
        gas += z * params.TxDataZeroGas
    }
    return gas, nil
}

Gas预估

相关源码位置:internal/ethapi/api.go

func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) {
    // Binary search the gas requirement, as it may be higher than the amount used
    var (
        lo  uint64 = params.TxGas - 1
        hi  uint64
        cap uint64
    )
    if uint64(args.Gas) >= params.TxGas {
        hi = uint64(args.Gas)
    } else {
        // Retrieve the current pending block to act as the gas ceiling
        block, err := s.b.BlockByNumber(ctx, rpc.PendingBlockNumber)
        if err != nil {
            return 0, err
        }
        hi = block.GasLimit()
    }
    cap = hi

    // Create a helper to check if a gas allowance results in an executable transaction
    executable := func(gas uint64) bool {
        args.Gas = hexutil.Uint64(gas)

        _, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{}, 0)
        if err != nil || failed {
            return false
        }
        return true
    }
    // Execute the binary search and hone in on an executable gas limit
    for lo+1 < hi {
        mid := (hi + lo) / 2
        if !executable(mid) {
            lo = mid
        } else {
            hi = mid
        }
    }
    // Reject the transaction as invalid if it still fails at the highest allowance
    if hi == cap {
        if !executable(hi) {
            return 0, fmt.Errorf("gas required exceeds allowance or always failing transaction")
        }
    }
    return hexutil.Uint64(hi), nil
}

EstimateGas采用二分查找法获取要评估交易的gas值。二分查找的下限是param.TxGas, 如果args参数指定Gas大于param.Gas,那么二分查找的上限就是args.Gas,否则以当前pending块的block gas limit(后面简称BGL)作为二分查找的上限。doCall函数模拟智能合约的执行,经过多次尝试找到智能合约能够成功运行的最佳gas值。

由于二分查找的上限和BGL有关,而BGL和不是固定不变的,因此每次gas评估的结果不一定都是相同的,可能每个区块周期就会变动一次。

在实际进行gas评估的时候,可能会出现类似下面的错误

{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"gas required exceeds allowance or always failing transaction"}}

该错误出现的最可能是合约执行中出错。

参考链接

How do you calculate gas limit for transaction with data in Ethereum?

相关文章

  • 以太坊GasLimit的计算方法

    静态Gas的计算 以太坊黄皮书上说的gasLimit的计算方法: gasLimit = Gtransaction ...

  • 基于DYDX闪电贷在Cofix和Uniswap之间套利

    由于在以太坊中的交易属性,在一笔交易中可以借出大量资金进行操作(不能超过gaslimit限制)。所以当各个交易平台...

  • 以太坊1.0和2.0有什么区别?

    虽然以太坊2.0依旧用“以太坊”命名,但以太坊1.0和以太坊2.0其实是完全不同的两种架构。以太坊1.0和2.0的...

  • 区块链2.0之以太坊

    区块链2.0之以太坊 一、什么是以太坊 以太坊的全称是Ethereum,简称ETH或ether。 以太坊被称为区块...

  • 区块链重要资料

    比特币 比特币官网比特币Wiki白皮书源代码 以太坊 以太坊爱好者以太坊Blog以太坊论坛以太坊Git白皮书

  • 以太坊源码解读(1)以太坊架构与模块结构

    以太坊架构与模块化结构 一:以太坊核心概念 EVM: 以太坊虚拟机,以太坊中智能合约的运行环境 Accounts:...

  • 第3章 以太坊应用开发基础

    以太坊开发环境搭建 配置以太坊环境** 安装go环境因为以太坊是Go语言进行开发的,所以要在本机上安装以太坊,首先...

  • 如何购买以太坊

    以太坊ETH是一种区块链技术,而以太币是以太坊的原生代币。随着以太坊价格的暴涨以及数字货币被人们所承认,以太坊交易...

  • 如何购买以太坊

    如何购买以太坊 以太坊ETH是一种区块链技术,而以太币是以太坊的原生代币。随着以太坊价格的暴涨以及数字货币被人们所...

  • 《【砂糖橘解说】ETH(以太坊)是什么?》

    《【砂糖橘解说】ETH(以太坊)是什么?》 一、以太坊的发售 Ethereum(以太坊),简称ETH。 2013年...

网友评论

    本文标题:以太坊GasLimit的计算方法

    本文链接:https://www.haomeiwen.com/subject/wukdzqtx.html