Blockchain is great, but just as any great new technology it still has a long way to go in terms of infrastructure and development. This article covers one of the many challenges of blockchain development that iXledger engineers have tackled.
The Ethereum Transaction & Nonce
Before going into the details, we need to know how transactions work in Ethereum. A transaction is simply a signed data package sent from an externally owned account to another account on the ethereum network. The transaction consists of a set of values (which you can find here) and a nonce which is what we are mainly interested in. Keep in mind that we are talking about the transaction nonce here and not the proof-of-work nonce:
- Transaction nonce – The number of transactions made by the sender.
- Proof-of-work nonce – A meaningless value in a block which can be adjusted in order to try to satisfy the proof of work condition
When an account sends a new transaction, then the transaction nonce is incremented. That may not sound very useful! However, the transaction nonce is what stops people doing replay attacks on your account (e.g. re-running your transactions and draining your crypto). When two transactions with the same nonce enter the system, one of them is processed while the other is discarded which means there is no way of a transaction being processed multiple times. Another thing to consider is that future nonces that have a “gap” between the actual nonce and the new transaction nonce will not be fulfilled until that “gap” is filled.
If you sent multiple transactions with your account and your 3rd transaction failed, then all subsequent transactions will be stuck and won’t process until a 3rd transaction has been processed.
Transaction Signing: Node vs Offline
In order for a transaction to be processed by the network, it needs to be packaged and signed with a private key of an externally owned account. Usually the blockchain node handles everything, however this could be a security risk because you’re sending your private key over the network to the blockchain node. Another way of doing this is to sign your transaction outside the blockchain node and deliver the signed package to the node for processing. This method is used by hardware wallets and ensures that your private key is never sent in a public place, only the signed transaction. The complexity here arises from the fact that you need to build and sign your transaction.
This is where the tricky part comes in. Let’s consider that an application needs to do transactions in bulk for every customer, you will have to make sure that the nonces are correctly set for each transaction. There are ways of getting the transaction count through Ethereum’s JSON RPC API calls such as eth_getTransactionCount or a library. Unfortunately, this will not work most of the time; this functionality retrieves the transaction count for transactions in the current blocks and potentially pending block, what it doesn’t take into consideration is the possibility of having additional transactions residing in the transaction pool (txpool). This would then return you the wrong nonce which has already been used by a transaction in the txpool.
Potential solution: Resolve the nonce in your application using the txpool
- Even if eth_getTransactionCount doesn’t return all possible transactions, you can still retrieve the txpool, check for potential transactions there and increment the nonce accordingly.
- Pro: Ensures you have the correct nonce almost always (exception is node being out of sync) and is node agnostic.
- Con: Inefficient because you will need to fetch and iterate for every transaction you create.
Potential solution: Use a Parity node implementation
- The Parity node offers richer functionality compared to Geth and one of it is being able to get the nonce value using nextNonce(address).
- Pro: More efficient nonce handling done on the blockchain node compared to the first solution.
- Con: Limits the nodes your application can connect to, which is not ideal.
Potential solution: Completely handle the nonce within your application
- A potential solution would be to create your custom transaction manager which is responsible for sequencing your transactions and allocating the nonces without the need to constantly query the nodes.
- Pro: Likely to be faster than the other two potential solutions
- Con: More isolated from the overall state of the blockchain which brings its own set of issues
In summary, there’s multiple potential solutions each with their pros and cons, as well as multiple additions and improvements such as transaction retrying, cancelling, etc. What is important to remember is that the whole blockchain ecosystem is still new, with many challenges and it’s up to us as Software Engineers to share our knowledge and help improve it.
Author: Valdi Kamenarov
|Sounds good? We are hiring talented software engineers. Join us for the opportunity to innovate with blockchain, grow your career, solve challenging engineering problems, take on more responsibility and work with a highly talented team. Check out https://stag.ixledger.com/careers/.|