zoukankan      html  css  js  c++  java
  • 以太坊 EVM内交易执行分析(一)

     以太坊上交易最终都会由EVM进行解析存入数据库,今天就来探讨一下,一笔交易是如何别EVM执行的。我们可以把交易分为三种。(注意,和交易相关的模块很多,交易的生命周期存在于整个以太坊中,我们这次只是分析和EVM相关的部分。)

         1、以太币转移,两个账户之间只发生了以太币的转移。

         2、合约创建,用户创建智能合约的交易。这类交易的to地址都是空着的。

         3、调用合约,用户去调用智能合约中的某个函数,这类交易中data信息包含了需要调用的函数hash值的前4个字节,以及参数。例如基于ERC20的Token转账就是这种类型,前四个字节是0xa9059cbb表示transfer(address _to, uint256 _value),后边跟了两个参数,to地址和交易数量。

         最好结合代码理解一下。

    https://github.com/ethereum/go-ethereum/blob/461291882edce0ac4a28f64c4e8725b7f57cbeae/core/vm/evm.go

        以太币转移

        先看一下以太币转移类型的交易,这类交易比较简单,主要函数是由context中的两个函数完成的,CanTransfer CanTransferFunc。

    type Context struct {
    // 账户余额够不够
    CanTransfer CanTransferFunc
    // 把eth转移给另外一个账户
    Transfer TransferFunc
    // 对入参n返回一个hash
    GetHash GetHashFunc

    // Message information
    Origin common.Address // Provides information for ORIGIN
    GasPrice *big.Int // Provides information for GASPRICE

    // Block information
    Coinbase common.Address // Provides information for COINBASE
    GasLimit uint64 // Provides information for GASLIMIT
    BlockNumber *big.Int // Provides information for NUMBER
    Time *big.Int // Provides information for TIME
    Difficulty *big.Int // Provides information for DIFFICULTY
    }
     

    下边具体分析一下怎么实现的。


    func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
    return db.GetBalance(addr).Cmp(amount) >= 0
    }

    func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
    db.SubBalance(sender, amount)
    db.AddBalance(recipient, amount)
    }
        怎么样是不是so easy,一眼就看出来了;就是调用数据接口,实现数据库的数据的修改就可以了,对账户的余额进行增加、减少和查询;当然实际情况并非这么简单,之所以看着这么简单,就是我们常说的解耦;后续我会继续分析state和数据库等模块,那会儿我们就会有更清晰的认识。

    合约创建调用合约

     

    合约创建,evm.Create的逻辑和Call方法比较类似的。

    call和create几点不同:

    1)由于智能合约的创建是没有to地址的,所以SetCallCode方法的参数是从直接有用户传进去的的;而call则不一样,例如你转账erc20代币的时候,to地址是合约地址,所以SetCallCode方法的入参则是从to地址的关联的code中获取的。

    2)智能合约创建是一个从无到有的过程,所以statedb中没有合约的地址和账户,所以创建合约地址和账户是必然的过程。

    3)call()的input类型为[]byte,和create()的code类型同样为[]byte;这两者从交易的角度是一样的;但是当系统解析到to地址时,才有了分化;to地址不为空,则tx.data被当作contract的input,to地址为空的时候,则tx.data被当作contract的code。

         还有后续继续分析一下,交易是如何被解释器具体分析执行的。

  • 相关阅读:
    node.js 安装后怎么打开 node.js 命令框
    thinkPHP5 where多条件查询
    网站title中的图标
    第一次写博客
    Solution to copy paste not working in Remote Desktop
    The operation could not be completed. (Microsoft.Dynamics.BusinessConnectorNet)
    The package failed to load due to error 0xC0011008
    VS2013常用快捷键
    微软Dynamics AX的三层架构
    怎样在TFS(Team Foundation Server)中链接团队项目
  • 原文地址:https://www.cnblogs.com/405845829qq/p/10071658.html
Copyright © 2011-2022 走看看