以太坊交易流程

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

  • 构建原生交易对象

  • 对交易签名

  • 本地验证交易

  • 交易广播

  • 矿工节点接受交易

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

  • 本地节点同步新区块

构建原生交易对象

假设有一个function叫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'
};
  • Nonce:每个以太坊帐户都有一个名为nonce的字段,用于跟踪帐户执行的交易总数。 对于每个新交易Nonce都会递增,这样网络就可以知道交易需要执行的顺序。 Nonce也用于重放攻击的保护。
  • gasPrice:发起交易的人愿意为此交易支付的gas价格。 如果在主网上执行交易,有个网站可供参考,它建议应该为一笔交易设置d额天然气价格(https://ethgasstation.info/)以便在合理的时间内交易成功。 天然气价格以Wei为单位测量,范围从0.1-> 100 + Gwei。
  • gasLimit:发起交易的人愿意为此次交易支付的最大gas的数量。 这个值确保了如果执行恶意交易的问题(如无限循环),账户并不会耗尽所有资金。 交易执行完成后,剩余的gas将被发回交易发起人账户。同时,这个值也限制了一个区块的大小。gasLimit是基于市场的供需关系的,发起交易的人有权定价,矿工有权选择接受或拒绝,这也是以太坊在经济学上的一个体现。
  • to:这笔交易要转账的地址。
  • value:交易想要发送的金额(单位ether)。 当我们执行voteForCandidate时,默认不发送任何ether所以它的值为0。
  • data:首先从ABI获取到voteForCandidate(bytes32) 的签名,然后计算哈希值
> web3.sha3('voteForCandidate(bytes32)')
'0xcc9ab267dda32b80892b2ae9e21b782dbf5562ef3e8919fc17cab72aa7db9d59'

然后选取高4位:0xcc9ab267 ,假设传的参数是“abc”,把它转换为bytes32然后与刚才的哈希值相拼接。

对交易签名

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

const privateKey = Buffer.from('e331b6d69882b4ab4ea581s88e0b6s4039a3de5967d88dfdcffdd2270c0fd109', 'hex')

const txn = new EthereumTx(rawTxn)
txn.sign(privateKey)
const serializedTxn = txn.serialize()

本地验证交易

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

交易广播

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

transactionId = sha3(serializedTxn)

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

矿工节点接受交易

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

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

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

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

本地节点同步新区块

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

results matching ""

    No results matching ""