Cómo poner en cola transacciones firmadas simultáneas

He escrito un servidor API simple NodeJSque usa web3(versión 1 beta 27) para interactuar con un nodo de paridad remoto.

La tripa de la llamada es la siguiente

const invoke = async (req, res) => {
  const { params: { address } } = req
  try {
    const theContract = new web3.eth.Contract(abi, contractAddress, { from: SENDER_ADDRESS })
    const fn = theContract.methods.doTheThing(address)
    const account = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY)
    const data = fn.encodeABI()
    const nonce = await web3.eth.getTransactionCount(SENDER_ADDRESS, 'pending')
    const payload = {
      nonce,
      data,
      gas,
      from: SENDER_ADDRESS,
      to: contractAddress
    }
    const signedTx = await account.signTransaction(payload, account.privateKey)
    const { rawTransaction } = signedTx
    const response = await web3.eth.sendSignedTransaction(rawTransaction)
    const { transactionHash: tx } = response
    res.json({ tx })
  } catch (err) {
    res.status(500).json({ error: err.message })
  }
}

Esto funciona perfectamente si solo hago una llamada a la API a la vez, e incluso funciona bien si hago algunas llamadas que se superponen aproximadamente. (lo probé con curl usando varias ventanas de terminal)

Pero si uso un script para llamar a la API muchas veces simultáneamente (que es una simulación razonable de una condición del mundo real), la mayoría de las llamadas fallan y dicenThere is another transaction with same nonce in the queue.

Una solución que me recomendaron es crear una personaldirección dentro de Parity en lugar de crear una dirección en forma de un par de claves pública/privada en mi máquina, pero esa no parece ser la mejor solución.

El problema es que web3.eth.getTransactionCount(SENDER_ADDRESS, 'pending')devuelve lo mismo noncesi la API se invoca demasiado rápido. Una idea es que simplemente podría volver a intentarlo si el error detectado incluye el There is another transaction with same nonce in the queue.mensaje, pero eso parece frágil, por decir lo menos.

¿Cuál es la forma correcta de poner en cola solicitudes simultáneas como esta?

tendrá que implementar su propia lógica para manejar el nonce. Este es un problema muy común. Lo más simple que puede hacer es obtener el nonce una vez del nodo e incrementarlo en la memoria cada vez que desee firmar y enviar una nueva transacción. Este es un enfoque muy ingenuo, por supuesto. Deberá encargarse de la transacción fallida, por ejemplo, debido a un error de red y asegurarse de no crear una brecha de nonce, es decir, enviar la transacción con un nonce más grande que el actual.
¿Encontraste una buena solución para esto?

Respuestas (1)

Puede usar la solicitud por lotes, le permite enviar transacciones de un pedido específico:

http://web3js.readthedocs.io/en/1.0/web3-eth.html?highlight=batch#batchrequest

la solicitud por lotes no ayuda, ya que cada llamada API es completamente independiente entre sí.
No entiendo. ¿Cuál es el problema? lote le permite hacer cola para cualquier llamada/transacción que desee realizar. No le importa lo que hay dentro.
La API solo llama a la función con una dirección. Miles de entidades externas independientes pueden invocar la API. Cada llamada a la API es exclusiva entre sí, por lo que no hay nada que procesar por lotes.
Oh, está bien, malentendido. En mi conocimiento, no hay manera de hacer eso. Blockchain no es algo destinado a ser rápido (al menos por ahora)