I'm writing a system where some transactions have to be automatically detected, and wait for 30 blocks to ensure they're confirmed. What I do is that I read all new blocks, and find the transactions that belong to my addresses.

I'm using geth with getBlockByNumber RPC call, and then when I find a transaction that belongs to me, I put it in a mempool and wait for 30 blocks to pass, and then consider the transaction final.

The question: How can I detect cancelled transactions to prevent double-spending?

I can imagine a situation where a block becomes orphaned and/or canceled in some way. Before considering the transaction final, how can I check that the transaction is still valid and wasn't canceled in some way?

Is it sufficient to just check the same block (by number) before considering the transaction final, and check that the transaction is still there? Are there other scenarios that I have to worry about? (uncle blocks, etc.) How can I check this systematically?

1 Answer 1


It is possible that after a chain reorganization a transaction will be in another block. For example if a transaction was mined in block 100, afte a reorg it is possible it ends up at block 102, or block 99.

In a blockchain like ethereum (secured by proof of work) you are never 100% sure a transaction will be reversed. But for example after 12 blocks confirmations you have a very high confidence it will not be reversed since it requires a very large amount of hash power.

To check if a transaction is in the blockchain you have to check the value returnd by web3.eth.getTransaction(txid) contains blockHash pointing to an existing block and that blockNumber have enough confirmations from the best block returned by web3.eth.blockNumber.

To validate a bockHash you can call web3.eth.getBlock(blockHash), if the block is not in the main chain it will return null.

  • Any reorganization of blocks will definitely change the blockHash of all the blocks involved, right? This means that as long as the blockHash is the same, then nothing has changed and the transaction I detected is still as is in the block where I found it. I'm asking because every time I scan, I move backwards in the chain and verify that block number N has the same hash that I found before. If the hash is changed, I drop that block from my record and keep moving backward further, until the hash matches, and if it does, I start scanning again from the next block there. Is that reasonable? Jul 13, 2018 at 1:39
  • Yes, that should work, a chain reorg that affects a transaction will change the blockHash.
    – Ismael
    Jul 13, 2018 at 2:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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