以太坊交易是如何从生成并在网络中广播的,如下总结七个步骤:
1. 构建原始交易对象
如下为原始交易对象字段:
var rawTx = {
nonce: '0x00',
gasPrice: '0x09184e72a000',
gasLimit: '0x2710',
to: '0x0000000000000000000000000000000000000000',
value: '0x00',
data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057'
}
字段说明
-
nonce: 记录发起交易的账户已执行交易总数。Nonce的值随着每个新交易的执行不断增加,这能让网络了解执行交易需要遵循的顺序,并且作为交易的重放保护。
-
gasPrice:该交易每单位gas的价格,Gas价格目前以Gwei为单位(即10^9wei),其范围是大于0.1Gwei,可进行灵活设置。
-
gasLimit:该交易支付的最高gas上限。该上限能确保在出现交易执行问题(比如陷入无限循环)之时,交易账户不会耗尽所有资金。一旦交易执行完毕,剩余所有gas会返还至交易账户。
-
to:该交易被送往的地址(调用的合约地址或转账对方的账户地址)。
-
value:交易发送的以太币总量。
-
data: 若该交易是以太币交易,则data为空;若是部署合约,则data为合约的bytecode;若是合约调用,则需要从合约ABI中获取函数签名,并取函数签名hash值前4字节与所有参数的编码方式值进行拼接而成。
2.签署交易
需要使用交易账户的私钥对原始交易对象进行签名,下面介绍使用MetaMask以及硬编码两种方式:
-
MetaMask:私钥只会存储在你的浏览器上,因此你是唯一有权访问你的账户和私钥的人。当你在浏览器上执行交易之时,插件会将你的函数调用转化成原始交易,并用你的私钥签署交易。 Metamask运行Infura运营的节点,并且使用这些节点来广播交易。
-
硬编码:如下使用了ethereumjs-tx库对交易进行签名,当然硬编码私钥的方式签名交易,不实用,但可以使用一台没有联网的计算机签署该交易。之后,可以复制已签署交易串,并使用联网的计算机将其广播至网络。另一个安全之策是使用 Ledger 或 Trezor 等硬件钱包。这类钱包存储了私钥,而签署交易的私钥已经编程进了硬件本身。它们需要联网的原因只是为了发布你的已签署交易。
var Tx = require('ethereumjs-tx');
var privateKey = "你的私钥";
var tx = new Tx(rawTx);
tx.sign(privateKey);
var serializedTx = tx.serialize();
web3.eth.sendRawTransaction(serializedTx.toString('hex'), function(err, hash) {
doSomething()
});
3. 节点验证
签署过后的交易会提交至以太坊节点。然后节点会验证已签名的交易,确保它是由交易账户签署过的。
4. 交易广播
节点验证通过后,会被广播至其对等节点,这些对等节点再将该交易广播给它们的对等节点,以此类推。一旦交易被广播至网络,会输出该交易的id,可以用它来追踪交易的状态。
5. 矿工节点接受交易
矿工节点的职责是将交易打包到区块上。矿工是交易池的维护者,交易先是被添加进交易池,再由矿工进行评估选择来打包。矿工一般将所有交易存储在根据gasPrice价格分类的池中。价格越高,该交易就越有可能被添加进下一个区块。这是矿工节点的常见设定。并且矿池可以容纳的交易数是有限的,gasPrice价格低的交易可能会被放弃。
对于释放阻塞在矿池中交易的方法是提高其gasPrice价格,并维持nonce值和from值不变,nonce和from可以确定标识一笔交易,并且提高的gasPrice必须大于原来价格的10%才可以。这样一来,当矿工接收到新交易时,价格更高的新交易会覆盖之前的交易,使得矿工更容易选择并挖中。
对于如何设置合理的gasPrice,可以参照网站https://ethgasstation.info/
6. 矿工节点挖中有效区块并将它广播至网络
矿工将选中的全部交易一起包含进区块。矿工只能选择一定量的交易添加进区块,受限于以太坊设置的单个区块gasLimit,换言之,交易的所有gas总数不能超过区块的gasLimit。
一旦矿工选择将交易包含进区块,这些交易将被验证并包含进一个待处理区块,工作量证明开始。某个矿工节点最终会找到一个有效的区块,并将这一区块添加到区块链上。就像上面介绍的节点广播原始交易一样,矿工节点也会将这一有效区块广播给其他节点。
7. 节点接收/同步新区块
最终,全网节点将接收这个新区块,并同步区块链。一旦接收到这个新区块,节点就会执行区块里的所有交易。结合我们使用的truffle调用合约代码, truffle会不断测验连接节点的区块链以求确认。一旦它发现交易被确认,就会执行 then()中的回调逻辑。
网友评论