将离线交易发送到主网是"flaky."

  • 本文关键字:flaky 离线 交易 ethereum
  • 更新时间 :
  • 英文 :


这是我用来以编程方式将签名交易发送到主网的代码:

import Web3 from 'web3'
import EthereumTx from 'ethereumjs-tx'
const web3 = new Web3(new Web3.providers.HttpProvider(INFURA_URL))
const Contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS)
const createItem = (name, price, nonce, callback) => {
console.log(`Nonce: ${nonce}. Create an Item with Name: ${name}, Price: ${price}`)
const data = Contract.methods.createItem(name, price).encodeABI()
const tx = new EthereumTx({
nonce: nonce,
gasPrice: web3.utils.toHex(web3.utils.toWei('4', 'gwei')),
gasLimit: 400000,
to: CONTRACT_ADDRESS,
value: 0,
data: data,
})
tx.sign(new Buffer(MAINNET_PRIVATE_KEY, 'hex'))
const raw = '0x' + tx.serialize().toString('hex')
web3.eth.sendSignedTransaction(raw, callback)
}
export default createItem

我必须在合同中批量创建(即填充)项目,并且我想以编程方式执行此操作。然而,虽然代码在 ropsten 中运行良好,但它无法在主网中发送所有交易;它只发送前几个事务,不发送其余事务。这些错误没有帮助,因为通常肯定会发生此错误:

Unhandled rejection Error: Transaction was not mined within 50 blocks, please make sure your transaction was properly sent. Be aware that it might still be mined!

我想知道其他人今天必须向以太坊主网发送大量交易时会怎么做。我做错了什么吗?

你基本上不能可靠地做你们想做的事情。以下是出现的一系列问题:

  • 事务仅以随机数顺序成功。如果早期随机数处于挂起状态(或者更糟的是,丢失了),则其他事务将挂起,直到早期随机数被消耗(或从内存池中删除)。

  • 对于
  • 交易何时从内存池中删除没有硬性规定。当您犯了一个随机数错误或中介随机数由于某种原因没有到达网络时,这是可怕的,因为您不知道当您最终发布该随机数时会发生什么。

  • 可以发送许多具有相同随机数的事务。他们很可能被gas价格选中(因为矿工被激励这样做)。当发生奇怪的事情时,一个有用的技巧是通过发送一堆高汽油价格、零价值交易来清除您的随机数。您可以将其称为增量方法。请记住,这是有代价的。

  • 许多工具做以下两件事之一来处理随机数:从getTransactionCount()实时读取或从getTransactionCount()读取,然后递增您发送的每个额外事务。这两种方法都不可靠:首先,交易有时处于待处理状态,但在池中尚不可见。如果汽油价格低于safemin,这似乎尤其会发生,但我不完全确定这里发生了什么。第二,如果任何其他系统发送具有相同地址的交易,它将不起作用。

那么,我们如何解决这个问题呢?

  • 智能合约是一种将交易从许多发送者随机数减少到很少发送方随机数的简单方法。编写一份发送所有不同交易的合同,然后将预算发送到该合同。这是解决问题的一种相对较高的成本(就时间/精力/专业知识而言)的方法。

  • 无论如何,还是要做,批量风格。当我不得不手动发送许多交易时,我将它们批处理成 10 个左右的一组并去做。每次手动递增随机数(因为交易通常尚未在网络上),然后等待足够长的时间让所有交易确认。不要依赖Etherscan或类似设备上的待处理交易来确定这是否有效,因为事情经常从这个水平上不可预测地消失。切勿将随机数重用于不是 0ing 高 gas 交易的不同事务 - 你会搞砸它,最终你会错误地发送相同的交易两次。

  • 序列 化。您逐个发布交易,等待它确认,增加您的随机数。这可能是易于实施的自动化解决方案中最好的。它不会失败。如果您有恒定的事务流,它可能会永远缓冲。它还确保您每个区块永远不会有多个事务,将您的吞吐量限制在每分钟 4 个左右。

  • 触发并重试。这有点粗略,因为它涉及为不同的事务重用随机数。将您的所有(或一些大批量)交易发送到网络。如果有任何失败,请从故障随机数重新启动并再次发送。可能有一个更智能的解决方案,您只需尝试交换丢失的随机数。您需要非常小心,切勿发送秘密存在于待处理但不可见池中的事务。

  • 每笔交易的新地址。将资金分配到您自己的地址的缓冲步骤可确保您永远不会为其他人搞砸。不过,它确实使您的交易时间和成本翻倍。

我认为大多数大型服务(如池和交易所)所做的是触发和重试的某种变体。其中一些可以通过将预算分摊到几个可用的地址(减少冲突频率)来改进。

最新更新