以太坊交易流程
交易是以太坊的核心部分,当你和以太坊区块链交互时就是在执行交易并修改状态,一个完整的流程包括以下几点:
- 构建原生交易对象
- 对交易签名
- 本地验证交易
- 交易广播
- 矿工节点接受交易
- 矿工节点发现有效区块并向全网广播
- 本地节点同步新区块
构建原生交易对象
假设有一个 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() 块内的代码(按照我们的程序执行)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论