2

I am wondering if there is a way to detect forks that may happen to an Ethereum chain. I looked in web3 library, but couldn't find anything.

Any idea?

Noureddine
  • 339
  • 1
  • 12
  • by forks you mean forks that act like network upgrades (hard/soft forks) or cases when the active (main) chain is switched chain by mere chance (for example when the miners are non synced)? – leonprou Apr 28 '19 at 12:23
  • 1
    I mean the second case. – Noureddine Apr 28 '19 at 17:01
  • This question on bitcoin might help. https://bitcoin.stackexchange.com/questions/44437/how-to-detect-a-fork-with-bitcoin-cli – Spyder Apr 30 '19 at 07:16
  • I think this can answer your question https://ethereum.stackexchange.com/questions/1187/how-can-a-dapp-detect-a-fork-or-chain-reorganization-using-web3-js-or-additional – leonprou May 01 '19 at 13:40
  • It seems to be just detecting a fork without having more information about it. – Noureddine May 01 '19 at 14:41

2 Answers2

0

I will caveat this twice this by saying the proposed solution is probably not the direct answer...

1) Caveat 1: This is not simply consuming an API

Basically as far as I know there is no direct API that gives you the block "tree" of the latest blockchain state. The reason for this is because this state is effectively considered ephemeral, and if you don't explicitly ask to, is removed (pruned) for the underlying DB periodically. However this data structure is maintained on most Ethereum clients, you just have to expose this structure to the JSONRPC api.

I'll give an example, on EthJ there is a constructed called BlockStore that maintains what you're looking for, you can query for blocks by number through this function call:

public synchronized List<Block> getBlocksByNumber(long number){

    List<Block> result = new ArrayList<>();

    if (number >= index.size()) {
        return result;
    }

    List<BlockInfo> blockInfos = index.get((int) number);

    if (blockInfos == null) {
        return result;
    }

    for (BlockInfo blockInfo : blockInfos){

        byte[] hash = blockInfo.getHash();
        Block block = blocks.get(hash);

        result.add(block);
    }
    return result;
}

This data structure inherently stores which chain is the "main" chain, and has functions to modify the current "main", therefore you could technically store this information and expose it later (again not trivial, but it is there). See the rebranch function here for details.

So to clarify, if you wanted an API to do this you would need to:

  • Modify the kernel to expose this data structure.
  • Run and synchronize the kernel to the public Ethereum blockchain.
  • Grab data using your API to whatever service is consuming it.

I used EthereumJ for simplicity, all Ethereum clients expose this structure.

Yao Sun
  • 36
  • 1
0

There is probably a more technical solution than this, but I recently encountered the problem of needing to know if a chain-reorganisation occurred for a dapp I'm building which makes use of recent blocks.

The simple (yet somewhat hacky) solution I came up with was to deploy a simple contract which has a single function that returns the last few block hashes, as well as the current block number. The function could look something like this

function get_history() view external returns (uint block_number, bytes32[10] memory hashes){
  for(uint i = 0; i < 10; i++){
    hashes[i] = blockhash(block.number - i - 1);
  }
 return (block.number, hashes);
}

The length of the array can be anything up to 256, beyond that the block hashes aren't retrievable.

You can then call this function with web3.js either periodically or whenever a new block is mined. Using the return data, you can keep a record of which block hashes belong to which block number. If the function ever returns a block's hash which is different to a value you have recorded, you can be certain that a re-organisation has occurred, and trigger whatever behaviour you need.

AnAllergyToAnalogy
  • 3,553
  • 11
  • 23