Ethereum 将脱机事务发送到mainnet是;片状的;

Ethereum 将脱机事务发送到mainnet是;片状的;,ethereum,Ethereum,这是我用来以编程方式将签名事务发送到mainnet的代码: 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,

这是我用来以编程方式将签名事务发送到mainnet的代码:

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中运行良好,但它无法在mainnet中发送所有事务;它只发送前几个事务,不发送其余事务。这些错误没有帮助,因为通常保证会发生此错误:

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!

我想知道今天,当其他人不得不向以太坊mainnet发送大量交易时,他们会怎么做。有什么我做错了吗?

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

  • 事务仅在临时顺序中成功。如果一个早期nonce处于挂起状态(或者更糟的是,丢失),则另一个事务将挂起,直到该早期nonce被使用(或者从mempool中删除)

  • 对于事务何时从mempool中删除,没有硬性规定。当你犯了一个nonce错误或者中间nonce由于某种原因没有到达网络时,这是很可怕的,因为你不知道当你最终发布该nonce时会发生什么

  • 可以发送具有相同nonce的多个事务。它们很可能是由天然气价格决定的(因为矿商正是被激励这样做的)。当发生了一些奇怪的事情时,一个有用的技巧是通过发送一系列高油价、零价值的交易来清除你的暂时状态。您可以将其称为增量方法。记住这是有代价的

  • 很多工具都会执行以下两种操作之一来处理nonce:从getTransactionCount()实时读取,或者从getTransactionCount()读取,然后为发送的每个额外事务递增。这两种方法都不能可靠地工作:首先,事务有时是挂起的,但在池中还不可见。这似乎特别发生在天然气价格低于safemin时,但我不完全确定这里发生了什么。对于第二种情况,如果任何其他系统发送具有相同地址的事务,它将无法工作

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

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

  • 不管怎样,都要做,批量式。当我不得不手动发送许多事务时,我会将它们分批放入10个左右的集合中,然后进行处理。每次手动增加nonce(因为事务通常还不在网络上),然后等待足够长的时间以确认所有事务。不要依赖Etherscan或类似平台上挂起的事务来确定这是否有效,因为事情往往会在这一级别上不可预测地消失。千万不要将一个nonce重新用于一个不同的事务,而该事务不是一个非常高的gas事务-你会把它搞砸,最终会错误地发送同一个事务两次

  • 序列化。你一个接一个地发布一个事务,等待它确认,增加你的nonce。这可能是最容易实现的自动化解决方案。它不会失败。如果您有一个恒定的事务流,它可能会永久缓冲。它还可以确保每个块的事务数不能超过一个,从而将吞吐量限制在每分钟4个左右

  • 激发并重试。这有点粗略,因为它涉及对不同事务重用nonce。将所有(或部分大批量)交易发送到网络。如果出现任何故障,请立即从故障状态重新启动并再次发送。可能有一种更智能的解决方案,您可以尝试替换掉丢失的nonce。您需要非常小心,不要发送秘密在挂起但不可见池中的事务

  • 每笔交易的新地址。将资金分配到你自己的地址的缓冲步骤确保你永远不会为别人搞砸。但它确实使您的交易时间和成本增加了一倍


我认为fire和retry的一些变体是大多数大型服务(如池和交换)所做的。通过将预算拆分为几个可用的地址(减少冲突频率),可以改进其中的一些功能

你们基本上无法可靠地完成你们想要做的事情。出现了一系列问题:

  • 事务仅在临时顺序中成功。如果一个早期nonce处于挂起状态(或者更糟的是,丢失),则另一个事务将挂起,直到该早期nonce被使用(或者从mempool中删除)

  • 对于事务何时从mempool中删除,没有硬性规定。当你犯了一个nonce错误或者中间nonce由于某种原因没有到达网络时,这是很可怕的,因为你不知道当你最终发布该nonce时会发生什么

  • 可以发送具有相同nonce的多个事务。它们很可能是由天然气价格决定的(因为矿商正是被激励这样做的)。当发生了一些奇怪的事情时,一个有用的技巧是通过发送一系列高油价、零价值的交易来清除你的暂时状态。您可以将其称为增量方法。记住这是有代价的

  • 很多工具都会执行以下两种操作之一来处理nonce:从getTransactionCount()实时读取,或者从getTransactionCount()读取,然后为发送的每个额外事务递增。这两种方法都不能可靠地工作:首先,事务有时是挂起的,但在池中还不可见。这似乎特别发生在天然气价格低于safemin时,但我不完全确定这里发生了什么。对于第二个,如果任何其他系统se