I would like to create multiple transaction from the same address at the same time. Since every transaction needs nonce (tx count of the sender address) I can ask geth for the current count and create first tx, then increment nonce and create the next one and so on. Problems as I see them are:

  1. if one transaction does not get mined, none of the following will get mined (since nonce will be incorrect).
  2. what happens if some tx gets included in one block and some in the other block, order might become wrong. Is this reasoning correct?

If it is not, I'm wondering is there any better approach for this case.

  • I would be interested in first seeing what happens if you do send ~10-20 transactions "all at once" and at what point it fails. Please report back. – tayvano Apr 2 '16 at 4:09
  • tayvano, test of 30 transaction all at once below. The test were performed on-blockchain where I have not specified the nonce. – The Officious BokkyPooBah Apr 2 '16 at 16:09
  • @BokkyPooBah Please avoid posting a comment as an answer. A link could probably be used to avoid long comments. – eth Apr 2 '16 at 18:42
  • Yup. August getting used to this system. – The Officious BokkyPooBah Apr 2 '16 at 22:03

You have not stated whether you are sending your transactions while connected to the blockchain via geth (on-blockchain), or whether you are crafting your transaction while not connected to the blockchain (off-blockchain).

The answer by Paul S is referring to the off-blockchain crafting of transaction where you have to specify a nonce in the raw transactions you are then executing on the blockchain.

If you are sending your transaction on-blockchain, you can use the eth.sendTransaction(...) without a nonce.

For example, here are 3 transactions from the same "from" account to the same "to" account. There is no need to specify a nonce as it is automatically generated:

> eth.sendTransaction({from: '0x5e83b635f96da0752f991f0ebddc31249f452dea', to: '0x68acc3a13441b69016560d23e134c7931bbb27bb', value: web3.toWei(1, "ether")});
"0x92d6d2285b198b6b5cf80eca6d4292c9675fb53f47f786063df600d3be06dd09"
> eth.sendTransaction({from: '0x5e83b635f96da0752f991f0ebddc31249f452dea', to: '0x68acc3a13441b69016560d23e134c7931bbb27bb', value: web3.toWei(2, "ether")});
"0x0c1280c8b2f38aec032494913c1d0e65edd511fcd15e2424483f9bbf51c7172e"
> eth.sendTransaction({from: '0x5e83b635f96da0752f991f0ebddc31249f452dea', to: '0x68acc3a13441b69016560d23e134c7931bbb27bb', value: web3.toWei(3, "ether")});
"0x8b6998eea8b343a0f754cf2732a1f28caac3acdfbe97cca69f244f0614ea546a"

> eth.getTransaction("0x92d6d2285b198b6b5cf80eca6d4292c9675fb53f47f786063df600d3be06dd09");
{
  blockHash: "0x8456088424a4cacd8b394b4e11732e3c96ca77ab4a999c6ba62b38ab61116b58",
  blockNumber: 225,
  from: "0x5e83b635f96da0752f991f0ebddc31249f452dea",
  gas: 90000,
  gasPrice: 20000000000,
  hash: "0x92d6d2285b198b6b5cf80eca6d4292c9675fb53f47f786063df600d3be06dd09",
  input: "0x",
  nonce: 0,
  to: "0x68acc3a13441b69016560d23e134c7931bbb27bb",
  transactionIndex: 0,
  value: 1000000000000000000
}
> eth.getTransaction("0x0c1280c8b2f38aec032494913c1d0e65edd511fcd15e2424483f9bbf51c7172e");
{
  blockHash: "0x8456088424a4cacd8b394b4e11732e3c96ca77ab4a999c6ba62b38ab61116b58",
  blockNumber: 225,
  from: "0x5e83b635f96da0752f991f0ebddc31249f452dea",
  gas: 90000,
  gasPrice: 20000000000,
  hash: "0x0c1280c8b2f38aec032494913c1d0e65edd511fcd15e2424483f9bbf51c7172e",
  input: "0x",
  nonce: 1,
  to: "0x68acc3a13441b69016560d23e134c7931bbb27bb",
  transactionIndex: 1,
  value: 2000000000000000000
}
> eth.getTransaction("0x8b6998eea8b343a0f754cf2732a1f28caac3acdfbe97cca69f244f0614ea546a");
{
  blockHash: "0x8456088424a4cacd8b394b4e11732e3c96ca77ab4a999c6ba62b38ab61116b58",
  blockNumber: 225,
  from: "0x5e83b635f96da0752f991f0ebddc31249f452dea",
  gas: 90000,
  gasPrice: 20000000000,
  hash: "0x8b6998eea8b343a0f754cf2732a1f28caac3acdfbe97cca69f244f0614ea546a",
  input: "0x",
  nonce: 2,
  to: "0x68acc3a13441b69016560d23e134c7931bbb27bb",
  transactionIndex: 2,
  value: 3000000000000000000
}
  • 1
    i use web3.js all day (connected to geth as the provider) without fiddling with the nonce. Who's setting the nonce for me? – Paul S Apr 2 '16 at 15:35
  • 1
    Paul S, from github.com/ethereum/go-ethereum/blob/master/rpc/api/… it seems that the nonce will be guessed when not specified. – The Officious BokkyPooBah Apr 2 '16 at 16:06
  • sounds like a separate question is needed for the nonce. So I searched for the word 'nonce'. lots of good stuff to learn there. No need for a separate question. – Paul S Apr 2 '16 at 17:01

If you have transaction dependencies in your off-blockchain application you should wait until the prior transaction has been mined before submitting the next transaction.

Generally the process is

  1. Send a transaction, the result is a transaction hash
  2. Busy poll or wait on event to see if the transaction for that hash value was mined.

There aren't good succinct examples of this that I can put into a stackexchange post, but here are some links that show various ways of doing this:

How to tell when your transaction has been mined stack exchange Question

Ether Pudding has this built in, see synchronizeFunction in index.js for how this works. Makes your application code very clean using promises. However index.js is pretty hard to read...just trust me it works ;-)

You can busy poll for the transaction receipt

You can busy poll on the transaction to see if its block is valid. This is what ether-pudding does.

You can create an event filter whose callback fires on every block that's mined, and every time a block is mined you can use one of the above poll methods to see if your transaction was mined. This is possibly better than busy polling, though I've had some issues with the eventing system that are very hard to reproduce.

In all these cases, you don't want to wait forever, you'll want some sort of timeout. Generally in javascript you'll ether fire a callback to your application or return a fulfilled promise when a transaction is mined. I suppose you could use some of the other javascript idioms such as RXJS or Event but I haven't tried those for this purpose.

Do they need to be all at the same time, or can you include an arbitrary delay of say, 30 seconds before the next one fires off? This surely would eliminate any issues of you described. Much shorter times could almost certainly be used.

There is a real possibility of transactions not being sent / processed in the same order and therefore failing but it will depend on supplied gas, level of network activity, how quickly "at the same time" actually is, etc.

  • waiting 30 seconds isn't advisable, as mining times could vary. If you have order dependencies between transactions, wait until the previous transaction is mined, as that is positive confirmation. On a more advanced topic, if you are worried about double-spend, waiting until several blocks have been mined after the transaction has been mined. – Paul S Apr 2 '16 at 4:18
  • @PaulS There is no way to double-spend due to the nonce. Send a transaction with a nonce of 0, then 1, then 2. If the first is not mined, the 1st and 2nd will fail. If 2 "arrives" before 1, it will fail similarly. If you send them all with a nonce of 0, only the first one mined will go through. Etc. Etc. I believe 30 seconds will be enough time but I'm about to do a test myself here in a few minutes. – tayvano Apr 2 '16 at 4:22
  • What happens if on occasion a block gets reverted by the blockchain protocol? If you are outside the blockchain you might think you've sent ether, but you actually haven't. IMHO you have to track this happening for some critical types of transactions. (on blockchain, in your solidity code, it's not relevant because the block gets reverted and your state gets reverted with it) – Paul S Apr 2 '16 at 4:29
  • The web3.js docs have several examples of waiting for a transaction to be mined. In my experience magic timeouts are very fragile. – Paul S Apr 2 '16 at 4:31
  • @PaulS Why don't you post the web3 example as an answer as it is certainly useful in this context – tayvano Apr 2 '16 at 4:36

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.