I'm keeping a simple log of blocks, and storing them in an array. When a new block arrives, I add it to the array.

Let's say this is my block chain array:

E    <- tip
D
C
B
A

Now, say a new block arrives, extending a branch:

     Z    <- new tip
E    Y
D    X    <- new branch start
     C
     B
     A

Now the blocks C and D have been replaced in the main chain by X and Y.

Questions:

  1. Is there a way to detect that the latest block has extended a branch?
    • In other words, how can I detect whether blocks lower down in the array need to be replaced?
  2. How frequently does this happen?

EDIT: Initial solution is to check if the previousblockhash of the new block is equal to the hash of the tip in the array. If not, update the old tip, and keep working down through the array updating each block until their is a match for the previousblockhash.

up vote 3 down vote accepted

You can use the getchaintips RPC, which will list all tips of the known block tree, including branches that were never active.

You may see for example:

{
    "height": 420561,
    "hash": "000000000000000001cb02590846299c91794e9b9f422513cff4b9c1dd5c62a",
    "branchlen": 0,
    "status": "active"
},
{
    "height": 419698,
    "hash": "000000000000000004a3a78750438d0491b6335cbbe9c15099a6e55b6943e51a",
    "branchlen": 1,
    "status": "valid-headers"
},
{
    "height": 418868,
    "hash": "000000000000000000ba1d7d93ad1c7f04fb4a430fdee67c44fbdd3236f2b805",
    "branchlen": 1,
    "status": "valid-fork"
},

Here you can see that the current best valid chain we know of is at height 420561. There are also two forks:

  • One branching off at height 419697 and extending to height 419698. It has status "valid-headers", which means we heard about the headers for this block, but by the time they were verified, we already had an equivalent or better block available, so we did not attempt to download the forked block at height 419698.
  • One branching off at height 418867 and extending to height 418868. It has status "valid-fork", which means we actually heard about this block at a time when it was the best block, and proceeded to download and validate it, which was succesful. Later the branch was overtaken by the branch that is leading up to our current tip.

So this not only allows you to detect reorganizations, but gives information about all historic ones your node observed and/or went through.

  • Excellent. Do you also know what headers-only means? – inersha Aug 2 '16 at 16:13
  • valid-fork means we received and validated the blocks in this fork. valid-headers means we received the blocks but never bothered to verify them, as they were no longer the best chain when we got them. headers-only means we never even received the blocks. – Pieter Wuille Aug 2 '16 at 17:33
  • Why would a node receive a block header (headers-only) but not download the rest of the block? Or to put it another way, why would a node download a full block (valid-headers) if the node knows that we already have a valid block at the same height? – inersha Aug 2 '16 at 18:37
  • @inersha Because it may have learned of a better block that extends another chain after requesting the header, but before receiving the header. In that case we don't bother downloading the rest of the block data. – Pieter Wuille Aug 2 '16 at 19:37

Question 1

The chain with the most work needs to be the tip. I'm assuming you are working through bitcoind:

So I would simply go through the a list of all blocks received ever (A-E and X-Z) in my array and find the block with the most total work. You get this info from chainwork in the getblock api call on bitcoind. Assuming you have that available.

Then the current chain becomes the chain indicated by following prevblockhash backwards from the tip to the Genesis block. This should then result in a chain Z,Y,X,C,B,A. Any block not in this chain becomes orphan.

Question 2

You can then count forks that your node has seen in a couple of ways:

  • checking any blocks that are referenced by as the previousblockhash by multiple blocks.
  • by creating your own nextblockhash reference and counting the number of times you have more than one of these in a block.
  • counting the number of times you have multiple blocks in your array at the same height (though this will overestimate if there are multi-block forks).

I don't know exactly what the average fork rate is but there is not a single answer. As different nodes will see different forks. Using a public block explorer like blockchain.info might be a good source to get a feel for this.

On their data I count 78 orphaned blocks in the last 180 days. At a rate of 0.43 per day that should be close to the rate of forks. The rate of forking should be lower as I ignore forks longer than 1 block.

You should be able to crawl their API in a similar way to suggested above to find the fork rate. You would be dependent on the accuracy of their data which has had issues.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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