• ethereum/EIPs-170 Contract code size limit


    eiptitleauthortypecategorystatuscreated
    170
    Contract code size limit
    Vitalik Buterin
    Standards Track
    Core
    Final
    2016-11-04

     

    Hard fork

    Spurious Dragon

    Parameters

    • FORK_BLKNUM: 2,675,000
    • CHAIN_ID: 1 (main net)

    Specification

    If block.number >= FORK_BLKNUM, then if contract creation initialization returns data with length of more than 0x6000(2**14 + 2**13) bytes, contract creation fails with an out of gas error.

    如果合约的数据大小大于0x6000,那么该合约的创建将会失败

    Rationale

    Currently, there remains one slight quadratic vulnerability in Ethereum: when a contract is called, even though the call takes a constant amount of gas, the call can trigger O(n) cost in terms of reading the code from disk, preprocessing the code for VM execution, and also adding O(n) data to the Merkle proof for the block's proof-of-validity. At current gas levels, this is acceptable even if suboptimal. At the higher gas levels that could be triggered in the future, possibly very soon due to dynamic gas limit rules, this would become a greater concern—not nearly as serious as recent denial of service attacks, but still inconvenient especially for future light clients verifying proofs of validity or invalidity. The solution is to put a hard cap on the size of an object that can be saved to the blockchain, and do so non-disruptively by setting the cap at a value slightly higher than what is feasible with current gas limits.

    目前ethereum仍有一个脆弱点:当一个合约被调用时,即使它使用的是固定的gas值,这个调用仍然会触发O(n)量级的花销在从硬盘中读取代码、对VM执行的代码进行预处理和将O(n)数据添加到Merkle证明中以验证块的有效性上。在目前的gas水平下,这是可以接受的,即使不是最理想的。但是在未来可能被触发的较高的gas水平的情况下,可能很快由于动态气体限制规则而其将成为一个更大的担忧——可能不像最近的拒绝服务攻击那么严重,但仍然不方便,特别是对未来的轻客户端验证有效性或无效的证明。

    解决方案是对一个对象的大小设置一个硬盘的上限(在这里既为合约的数据大小不大于0x6000),该上限可以保存到区块链,并通过将上限设置在略高于当前气体限制的可行值的情况下进行非干扰性设置。

     

    References

    1. EIP-170 issue and discussion: https://github.com/ethereum/EIPs/issues/170
    2. pyethereum implementation: https://github.com/ethereum/pyethereum/blob/5217294871283d8dc4fb3ca9d8a78c7d416490e8/ethereum/messages.py#L397

    该代码实现:

    • EIP 170: Contract code size limit - changes the maximum code size that a contract on the blockchain can have. This update prevents an attack scenario where large pieces of account code can be accessed repeatedly at a fixed gas cost. The maximum size has been set to 24576 bytes, which is larger than any currently deployed contract.改变区块链中能够有的最大代码大小.盖更新将防止在设定好的gas开销中,大片账户代码被重复接收的攻击方案,最大的大小设置为24576字节,这比目前所有被设置的合约都大
    def create_contract(ext, msg):
        log_msg.debug('CONTRACT CREATION')
    
        code = msg.data.extract_all()
    
        if ext.tx_origin != msg.sender:
            ext.increment_nonce(msg.sender)
    
        if ext.post_metropolis_hardfork() and msg.sender == null_address:
            msg.to = utils.mk_contract_address(msg.sender, 0)
            # msg.to = sha3(msg.sender + code)[12:]
        else:
            nonce = utils.encode_int(ext.get_nonce(msg.sender) - 1)
            msg.to = utils.mk_contract_address(msg.sender, nonce)
    
        b = ext.get_balance(msg.to)
        if b > 0:
            ext.set_balance(msg.to, b)
            ext.set_nonce(msg.to, 0)
            ext.set_code(msg.to, b'')
            # ext.reset_storage(msg.to)
    
        msg.is_create = True
        # assert not ext.get_code(msg.to)
        msg.data = vm.CallData([], 0, 0)
        snapshot = ext.snapshot()
        if len(ext.get_code(msg.to)):
            log_msg.debug('CREATING CONTRACT ON TOP OF EXISTING CONTRACT')
        #     return 0, 0, b''
    
        ext.set_nonce(msg.to, 1 if ext.post_spurious_dragon_hardfork() else 0)//
        res, gas, dat = _apply_msg(ext, msg, code)
    
        log_msg.debug('CONTRACT CREATION FINISHED', res=res, gas=gas, dat=dat if len(dat) < 2500 else ("data<%d>" % len(dat)))
    
        if res:
            if not len(dat):
                # ext.set_code(msg.to, b'')
                return 1, gas, msg.to
            gcost = len(dat) * opcodes.GCONTRACTBYTE
            if gas >= gcost and (len(dat) <= 24576 or not ext.post_anti_dos_hardfork())://合约创建钱判断gas的使用,合约的大小等
                gas -= gcost
            else://否则创建失败
                dat = []
                log_msg.debug('CONTRACT CREATION FAILED', have=gas, want=gcost, block_number=ext.block_number)
                if ext.post_homestead_hardfork():
                    ext.revert(snapshot)
                    return 0, 0, b''
            ext.set_code(msg.to, bytearray_to_bytestr(dat))
            log_msg.debug('SETTING CODE', addr=encode_hex(msg.to), lendat=len(dat))
            return 1, gas, msg.to
        else:
            ext.revert(snapshot)
            return 0, gas, dat
  • 相关阅读:
    node.js 版本管理工具 — nvm 下载、安装、配置及使用
    UNION [ All ]使用注意事项
    IDEA无法启动问题
    python + jinja2 + pandas 输出HTML报告
    PGbadger 慢日志分析工具
    密码复杂度策略 密码有效期 登陆失败策略
    postgresql 监控 洞察力
    linux 出错 “INFO: task xxxxxx: 634 blocked for more than 120 seconds.”的3种解决方案
    fsck 命令来修复磁盘
    could not locate a valid checkpoint record
  • 原文地址:https://www.cnblogs.com/wanghui-garcia/p/9664421.html
Copyright © 2020-2023  润新知