This is the code that I'm using to send signed transactions to mainnet programmatically:
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
I have to mass create (i.e. populate) items in my contract, and I want to do it programatically. However, while the code works well in ropsten, it fails to send all the transactions in mainnet; it only sends the first few transactions and doesn't send the rest. The errors are not helpful because this error is usually guaranteed to occur:
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!
I wonder how other people do when they have to send a lot of transactions to Ethereum mainnet today. Is there anything I'm doing wrong?
You basically cannot reliably do what you guys are trying to do. Here's a set of problems that arises:
Transactions only succeed in nonce order. If an early nonce is pending (or worse, went missing), the other transaction will pend until the early nonce has been consumed (or it gets removed from the mempool).
There's no hard rule for when a transaction will drop from the mempool. This is scary when you've made a nonce error or an intermediary nonce has not reached the network for some reason because you don't know what is going to happen when you finally post that nonce.
Many transactions with the same nonce can be sent. They are very likely to be selected by gas price (because miners are incentivized to do exactly that). One useful trick when something strange has happened is to clear out your nonces by sending a bunch of high gas price, zero value transactions. You might call this an increment method. Remember this comes with a cost.
A lot of tools do one of two things to handle nonces: a live read from getTransactionCount() or a read from getTransactionCount() followed by incrementing for each additional transaction you send. Neither of these work reliably: for the first, transactions are sometimes pending but not visible in the pool yet. This seems to especially happen if gas price is below safemin, but I'm not entirely sure what is happening here. For the second, if any other system sends a transaction with the same address, it will not work.
So, how do we work around this?
A smart contract is a straightforward way to reduce a transaction from many sender nonces to few sender nonces. Write a contract that sends all your different transactions, then send the budget to that contract. This is a relatively high cost (in terms of time/effort/expertise) way to solve the problem.
Just do it anyway, batch style. When I've had to send many transactions manually, I've batched them in to sets of 10 or so and gone for it. Incrementing the nonce manually each time (because the transaction is usually not on the network yet) and then waiting sufficiently long for all the transactions to confirm. Don't rely on pending transactions on Etherscan or similar to determine whether this is working, as things often vanish unpredictably from this level. Never reuse a nonce for a different transaction that isn't a 0ing high gas transaction - you will screw it up and you'll end up sending the same transaction twice by mistake.
Serialize. One-by-one you post a transaction, wait for it to confirm, increment your nonce. This is probably the best of the easy-to-implement automated solutions. It will not fail. It might buffer forever if you have a constant stream of transactions. It also assures you can never have more than one transaction per block, limiting your throughput to 4 a minute or so.
Fire and retry. This is a little sketchy because it involves reusing nonces for different transactions. Send all (or some large batch) of your transactions to the network. If any fail, restart from the failure nonce and send again. There's possibly a more intelligent solution where you just try to swap out the missing nonce. You'll need to be very careful you never send a transaction that is secretly in the pending-but-not-visible pool.
New address for every transaction. A buffering step of distributing funds to your own addresses ensures you never screw it up for other people. It does double your transaction time and cost though.
I think some variant of fire and retry is what most of the big services (like pools and exchanges) do. Some of these can be improved by splitting the budget over a few addresses as available (reducing the collision frequency).
Related
Now 99% of all interactions with the blockchain occur through Infuria or Alchemy (MetaMask - API Infuria).
Nobody raises their geth nodes.
Because of this, most people are skeptical about the word "decentralization", since the application still has a point of failure.
Why is it impossible to send transactions directly from the browser to the validator? What prevents this?
After all, this is the last obstacle before decentralization. If the browser/extensions stored hundreds of addresses of mining pools to which you can send a transaction, then such an application is almost fail-safe.
Generally, a signed transaction is sent from a wallet software to a node (in the peer-to-peer Ethereum network) that broadcasts it to the rest of the network as a "transaction waiting to be mined" (i.e. placed in a mempool).
Miners usually take transactions from the mempool and place them in blocks.
It is technically possible for a miner to accept a transaction from another source (or create and sign it themselves), and place it in a block.
But it comes with an inconvenience for the transaction sender - they need to wait until this specific miner mines a block containing their transaction. If they sent the transaction to the mempool instead, any miner could have picked it up and include in their block. And there is currently no standardized way of sending a transaction to the miner directly - so each might have a different channel and different rules.
So to answer your question:
Why can't transactions be sent directly to validators/mining pools?
They can. But it's just faster (for the transaction sender) to use the mempool and let the transaction be mined by anyone, instead of waiting for one specific mining pool to mine a block.
I had observed that the transaction send to the Parity node didn't processed,
and the error messsage "Rejected tx with old nonce" was shown.
The nonce value of the sendTransaction call was calculated so that it would become
the next nonce value. The message was not applicable to the situation.
There are three validator nodes in our Parity environment.
The version of Parity is 2.5.13, and it runs on Ubuntu Server 18.04.
The reproducibility of the phenomeon is not good, and it tends to be resolved with the passage of time.
Is there something that is considered to be the cause of the phenomeon?
When it will occur again, how will I survey the cause?
Only you with the private key can generate valid transactions. So you need to figure out why your code posts transactions with the same nonce to the Parity / mempool.
Check for duplicate transactions
Check for nonce reuse
I have an Azure function triggered via service bus which basically just does a long await (1 - 4.5 minutes (managed with cancellation token to prevent function timeout and host restarting)).
I want to process as many of these long await messages as I can. (Ideally about 1200 at the same time..)
First I ran my function on an App Service Plan (with Concurrent Calls = 1200), but I think each trigger creates a thread, and 1200 threads causes some issues.
So I decided to run it on Consumption, with Batch Size 32, with the idea what I can avoid creating tons of threads and scale out the consumption function instead when it sees the queue build up.
Unfortunately exactly the opposite happens, the Consumption function will process 32 messages, but never scales out even though the queue has 1000+ items in it. Even worse, some times the function just goes to sleep although there are still many items in the queue.
I feel my best option would be to group work in a message, so instead of 1 message = 1 long await, 1 message could be 100 awaits for example, but my architecture doesn't really allow to me group messages easily (because if some tasks fail but some succeed this is easily managed with dead letters, but with grouping I need to maintain state to track this). Is there an existing way to efficiently have many (independent) long running awaits on an azure function, either consumption or service plan.
I have recently downloaded the GUI wallet, and it gives the option to create contract based wallets and connect to them to a main account. What is the difference between using a contract based wallet and an account? And what should be used to store my ether?
Contract-based wallets are more robust and can be more secure. For example, a contract can be setup to require transfers over a certain threshold to be approved my multiple people/keys. Even if these keys all reside on your local computer, having to compromise even a slightly-improved 2 of 3 can provide far greater security than a single key alone.
Additionally, contracts benefit from transaction receipts, which contain a permanent log of all events. This makes it much easier to inspect the state and verify the history of a contract. For example, when a new transaction request is initiated against a wallet contract requiring multiple signatures, an event log for "ConfirmationNeeded" with the operation ID will be added. After the operation has received the appropriate number of signatures, a "MultiTransact" might occur containing the recipient, value, and associated data with the transaction.
Standard accounts benefit from none of this and can only send transactions, not respond autonomously.
Here are advantages and disadvantages for comparison.
Advantages of contract-based account wallets:
Funds are not stored on a single key.
You can cycle through management keys.
Mutisig functionality; only execute a transaction on majority rule (eg. Gnosis Multisig)
Allows for account recovery, in case your management keys are lost (eg. Argent).
Set transfer and withdraw limits enforced by the contract.
You can have access controls for keys, meaning you can restrict what methods a key can invoke. Useful when you want to delegate control to someone else but restrict what they can do.
Batched transactions; execute multiple transactions as 1 atomic transaction.
Defi protocol composition; easily integrate with other smart contracts (eg. one-click DAI saving rate accounts)
Meta transactions: pay your transaction costs using a different asset, like a token (eg. Gas Station Network). Relayers may also offer free transactions (eg. Authereum)
Disadvantages of contract-based account wallets:
Contract are susceptible to attacks; people write buggy code all the time (eg. Parity hack). An Externally-owned account (EOA) can't be hacked because there is no code to hack.
Backward incompatible features may render funds locked if contract not properly written. (eg. Istanbul hardfork gas cost changes)
Deployment costs; unlikes key pairs which doesn't cost anything to generate, there's a fee cost for deploying contract-based accounts.
Each user in my application has gmail account. the application needs to be in sync with incoming emails. for each user every 1 minute the application should ask gmail servers if there is something new. 99% of the time nothing is new.
From what I know gmail dosen't provide web-hooks
In order to reduce the load from my servers and specially from the DB I want to use the service bus queue in the following manner.
queue properties:
query method: PEEK_AND_LOCK
lock time : 1 minute
max delivery count: X
flow:
queue listener receiving message A from the queue and process it.
if nothing is new the listener will not delete the message from the queue
the message will be delivered again after lock time (1 minute)
basically instead of sending new message to the queue again and again to be processed we just leave them in the queue and relying on the re-delivery mechanism.
we are expecting many users in the near future (100,000-500,000) which means many messages in the queue in a given moment which needs to be processed each minute.
lets assume the messages size is very small and less the 5GB all together
I am assuming that the re delivery mechanism is used mainly for error handling and I wonder whether our design is reasonable and the queue is apt for that task? or if there are any other suggestions to achieve our goal.
Thanks
You are trying to use the Service Bus Queue as a scheduler which it not really is. As a result SB Queue will be main bottleneck. With your architecture and expected number of users you will find yourself quickly blocked by limitations of the Service Bus queue. For example you have only max 100 concurrent connections, which means only 100 listeners (assuming long-pooling method).
Another issue might be max delivery count property of SB Queue. Even if you set it to int.MaxValue now, there is no guarantee that Azure Team will not limit it in the future.
Alternative solution might be that you implement your own scheduler worker role (using already existing popular tools, like Quartz.NET for example). Then you can experiment - you can host N jobs (which actually do Gmail api requests) in one worker role (each job runs every X minute(s)), and each job may handle M number of users concurently. Worker role could be easily scaled if number of users increases. Numbers N and M can depend on the worker role configuration and can be determined on practice. If applicable, just to save some resources, X can be made variable, for example, based on the time of the day (maybe you don't need to check emails so often at night). Hope it helps.