Solidity--深入研究以太坊EVM

流程图 

Solidity--深入研究以太坊EVM_第1张图片

账户

账户类型 创建成本 交易发起 使用场景 作用
外部账户(私钥的所有者控制) 创建账户是免费的 可以自主发起交易 外部所有的账户之间只能进行ETH和代币交易 1、接受、持有和发送ETH 和 token 2、与已部署的智能合约进行交互
合约账户(由代码控制,部署在网络上的智能合约) 创建合约存在成本,因为需要使用网络存储空间 只能在收到交易时发送交易 从外部账户向合约账户发起的交易能触发可执行多种操作的代码,例如转移代币甚至创建新合约 1、接受、持有和发送ETH 和 token 2、与已部署的智能合约进行交互

交易

以太坊交易是指由外部账户发起的行动,即由人管理而不是智能合约管理的账户。例如Bob发送Alice 1 ETH,则Bob的账户必须减少1ETH,而Alice的账户必须增加1 ETH。此项操作发生在交易中会变更状态。Solidity--深入研究以太坊EVM_第2张图片

改变EVM状态的交易需要广播到整个网络。任何节点都可以在EVM上广播交易请求;此后,矿工将执行交易并将此产生的状态变化传播到网络的其他部分。交易的手续费和交易确认上链成为Gas费和挖矿。

 Solidity--深入研究以太坊EVM_第3张图片

交易对象需要使用发送者的私钥签名,证明交易只可能来自发送者,而不是被篡改或欺诈的交易。交易信息内容如下图所示:

{
  from: "0x2Bfb7fD07459764Dd98FeC880349e86756694739",
  to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a",
  gasLimit: "21000",
  maxFeePerGas: "300"
  maxPriorityFeePerGas: "10"
  nonce: "0",
  value: "10000000000",
}

Gas

如上所述,执行交易需要花费Gas。简单的转让交易需要21000个Gas。

假设Bob要向Alice发送1 ETH,需支付190gwei 的 baseFeePergas 和 10 gwei 的 maxPriorityFeePerGas,那么Bob需要支付以下费用:

(190 + 10 )* 21000 = 4,200,000 gwei == 0.0042 ETH

因此Bob的账户将会 -1.0042 ETH,Alice的账户将会 +1.0 ETH。过程中 -0.00399 ETH的基本费用,矿工保留消费 +0.000210ETH

交易生命周期

1、一旦发送交易,加密算法就会生成 交易哈希

2、然后将该交易转播到网络。并且与大量其他交易一起包含在一个集合中

3、矿工必须选择该笔交易并将其包含在一个区块中,用来验证交易并认为他”成功“

  • 如果网络繁忙,矿工未及时选择该交易,该交易将为等待状态

4、该交易收到“确认”后。确认的数量是自包含该交易的区块以来创建的区块数。区块数越大,交易被网络处理和承认的确定性就越强。

  • 最近的区块可能会被重组,但交易仍然有效,但包含在另一个区块中

交易流程实例

交易是以太坊的核心部分,当你和以太坊区块链交互时就是在执行交易并修改状态,一个完整的流程包括以下几点:

  • 构建原生交易对象

假设有一个voteForCandidate函数,是个投票合约,当用Web3js来调用时,就会产生交易对象:

txnCount = web3.eth.getTransactionCount(web3.eth.accounts[0])
var rawTxn = {
    nonce: web3.toHex(txnCount),
    gasPrice: web3.toHex(100000000000),
    gasLimit: web3.toHex(140000),
    to: '0x633296baebc20f35ec2e1c1b105d7cd1f6a0718b',
    value: web3.toHex(0),
    data: 
		'0xcc9ab24952616d6100000000000000000000000000000000000000000000000000000000'
};

交易中的数据说明如下表所示:

  • 对交易进行签名

以太坊网络需要知道交易发起人确实拥有该账户,以确保其他人不会假冒执行此交易。 向网络证明这一点的方法是使用与该账户相对应的私钥签署交易,这是一个证明你是你的过程。 过程像这样:

const privateKey = Buffer.from (
	'e331b6d69882b4ab4ea581s88e0b6s4039a3de5967d88dfdcffdd2270c0fd109', 'hex')
const txn = new EthereumTx(rawTxn)
txn.sign(privateKey)
const serializedTxn = txn.serialize()
  • 本地验证交易

已签名的交易提交给本地以太坊节点。然后本地节点将验证一签名的交易并确保它是真正有当前账户地址签名的。

  • 交易广播

签名交易由发起人的校验节点(eg:geth)广播给其他节点,一旦交易广播到网络,本地节点也会输出可以用来跟踪交易状态的交易ID。此交易标识是已签名交易对象的哈希:

transactionId = sha3(serializedTxn)

如果在公共的以太网网络上执行交易,跟踪交易状态的最佳方式是在etherscan.io上。 Etherscan的人员运行了几个节点,他们有一个很好的前端webapp与之交互。 当交易被他们的节点接受时,我们可以在他们的网站上看到待处理交易。

  • 矿工节点接受交易

矿工们是把交易打包在区块里的人。 在开始评估(gas价格是否合理)之前,矿工会维护一个交易池,一笔笔的交易被添加到交易池。

需要注意的是,矿工交易池可容纳交易的数量是有限的。 假设有一个热门的ICO或一个非常流行的dapp(如Crypto Kitties),人们都会以高gasprice提交交易,希望矿工在其他交易之前先处理。 如果大量较高的gasprice交易填满了交易池,那么我们刚刚发起的低价交易将被丢弃。 在这种情况下,我们甚至可能要重新发起交易。当然在nonce值不能变的前提下,我们提高gasprice就会提高被矿工处理的可能。

  • 矿工节点发现有效区块并向全网广播

一旦矿工选择要打包交易,交易将被验证并包含在待定块中,并且工作量就证明开始了。 矿工节点之一最终找到一个有效的块(通过解决PoW难题)并将该块添加到区块链中。 就像本地节点广播的原始交易会由其他节点接收到一样,矿工节点也将此有效块广播到其他节点中。

  • 本地节点同步新区块

最终,本地节点将收到此新块并将其同步到区块链的本地副本。 在接收到新块时,本地节点执行块中的所有交易。如果使用truffle的话,它会不断向区块链轮询确认, 一旦看到交易被确认,就会执行then()块内的代码(按照我们的程序执行)。

以太坊交易池

  • 交易池的主要功能

1、缓存交易

2、在打包区块前,对交易进行验证

3、过滤无效交易

4、惩罚恶意发送大量交易的账户

  • 流程图Solidity--深入研究以太坊EVM_第4张图片

用户可通过以太坊钱包或者调用以太坊节点API发送交易交易到一个运行中的以太坊geth节点。因为交易是通过节点的API接受,此交易会被视为来自本地(绿色交易块),经过校验和处理后进入交易池由矿工选择打包;如果交易是非矿工节点广播来的,此交易会被视为来自外来的(红色交易块),也会经过检验和处理进入交易池由矿工选择打包。矿工节点对于本地交易优先级会高于外来的恶交易。

  • 交易管理

主要分为可执行交易和非可执行交易。可执行交易是指从交易池中选出一部分交易执行,打包到区块中。非可执行交易相反,任何刚进入交易池的交易均属于可执行状态,在某一个时刻才会变为可执行状态。两种交易状态分别记录在pending容器中和queue容器中。交易池存在内存中,不会无限大,若超过阀值就需要对交易池中的交易进行清理。pending的容量默认是4096,queued的容量默认是1024。

  • 交易池中数据来源

1、本地提交,第三方应用通过调用本地以太坊节点的RPC服务所提交的交易

2、远程同步,是指通过广播同步的形式,将其他以太坊节点的交易数据同步至本地节点

3、交易池中交易被Miner模块获取并验证,挖矿成功后写进区块并被传播

4、 Miner取走交易是复制,交易池中的交易并不会减少,直到交易被写进规范链后才从交易池删除

5、交易如果被写进分叉,交易池中的交易不会减少,等待重新打包

  • 校验交易合法性

1、不允许交易数据超过32KB,防止DOS攻击

2、不允许转账金额为负数(实际上外部接受的交易数据属于RLP编码,无法处理负数)

3、防止程序错误,每笔交易会有GAS上限,同时为了控制区块大小避免区块的总消耗异常,区块 GAS也有上限。如果超过,交易将不能打包到区块,交易池也会直接拒绝超过限制的交易

4、每笔交易都需要携带交易签名信息,并从签名中解析出签名者地址,若解析失败将拒绝交易

5、以太坊每个账户的存在一个数字类型Nonce字段,是有序数字。每次交易都会+1,该Nonce可以表示为已打包了x次交易。因此交易池中不允许出现交易的Nonce小于账户当前Nonce的交易

6、在交易池中,会检查该账户余额,若资金不足会导致交易失败

7、若交易GAS上限低于已知的最低GAS开销,会导致交易失败

  • 进入交易队列Solidity--深入研究以太坊EVM_第5张图片

交易池会先采用一个txLookup跟踪所有交易。同时根据本地优先原则将交易划分为queue和pending两部分。在进入交易队列之前,将判断所有交易队列是否达到上限,若达到上限,将会移除掉交易池或当前交易中优先级最低的交易。因本地交易优先级高于外来交易交易,所以当受到外来交易,若低于最低gasPrice就会拒绝该笔交易。

为了高效获得不同价格的交易,交易池已经将交易按gasPrice从低到高实施排列。如果同一笔交易上调交易费上调10%以上的手续费将会被提前交易。

你可能感兴趣的:(智能合约,以太坊,学习,安全)