My dev blog where I dive deep into TypeScript, Postgres, Data science, Infrastructure, Ethereum, and more...

Solana vs Ethereum for relaying transactions

15th Aug 2024

Sometimes you want your backend to submit blockchain transaction so that your users don’t have to. This is called a relayer.

I already built this for Ethereum and EVM-based chains, and it definetely has it’s quirks. This post explores how transaction relaying works on Solana.

Transactions in EVM

In EVM, we can send lots of transactions by making sure we increment the nonce each time.

Transactions in EVM are always sequential. Transaction 3 can never go through before transaction 2 goes through. When building a relayer, this means that a single transaction failing can cause the whole pipeline to get clogged.

Does it work the same way in Solana?

How it works in Solana

To test this, I wrote a script using @solana/web3.js that send tokens.

Sending one token transaction works nicely

Sending 50 token transactions in sequence one by one works nicely (but takes time)

What about trying to send tokens 50 times all at once? Something weird happens. All the transactions go through instantly, but they all become the same! It’s just one transaction hash. The system probably sees them as the same and prevents double spends in this way.

Making all the 50 transactions different (with a varying amount), makes it possible to submit them all at once and get 50 different transactions (super fast). Yay!

It seems that Solana is good at executing transactions in parallel. They don’t have the same troublesome nonce system as EVM.

But how do they prevent double spends?

Solana uses “Recent Blockhashes” to prevent double spends

When submitting a transaction, Solana checks if your signed transaction already exists on-chain. Since the size of the whole blockchain is huge (300TB), only the last 150 blocks are checked. If your transaction is already there, it gets discarded. If your transaction is older than 150 blocks, it also gets discarded.

This has two important side effects:

  1. Transaction expiration. 150 blocks takes around 80-90 seconds. This means that transactions that are not submitted and accepted on-chain during this time-frame are dead forever.
  1. Impossible to submit multiple equal transactions in short timeframes. Demonstrated by my testing above, submitting lots of completely equal transaction in a very short timeframe will make them duplicate and avoiding their execution.

Transaction expiration is actually great when creating a relayer system. It makes the system more reliable and simpler. It means that I can be sure that a transaction has failed and will never be seen on-chain after the time period. Transactions in EVM are different, they can fly in the air for days and then suddenly get accepted.

The second point about short timeframes isn’t a concern in most real-world applications, but worth keeping in mind. Who would submit a hundred completely equal transactions in the same sub-second? Doesn’t make sense.

PS: It’s worth noting that if you want long-lived transaction signatures, Solana has a solution for that called Durable Nonces. I imagine that can be useful for things like multi-sig transactions and scheduled transactions

Recap

  • Transactions in solana are signed with a recent_blockhash instead of the nonce in ethereum.
  • If the recent_blockhash is too old, the transaction is discarded
  • Solana doesn’t care about sequentiality, a transaction submitted now can arrive on chain before a transaction submitted 30 seconds ago
  • In a relayer system, transactions can’t clog the pipeline in the same way as is common in EVM
 
 

Tools