I was working on an blockchain indexer and explorer, and as I was trying to figure out how to calculate the returned “medianTime” from the “getblockchaininfo”, I realized that the value is not what I was expecting it to be.
This was in an C# implementation of similar code to Bitcoin, so I initially thought it was a bug in the .NET implementation. Then I had a look at the C++ implementation and to me it appears to be the same.
0 static constexpr int nMedianTimeSpan = 11;
1
2 int64_t GetMedianTimePast() const
3 {
4 int64_t pmedian[nMedianTimeSpan];
5 int64_t* pbegin = &pmedian[nMedianTimeSpan];
6 int64_t* pend = &pmedian[nMedianTimeSpan];
7
8 const CBlockIndex* pindex = this;
9 for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
10 *(--pbegin) = pindex->GetBlockTime();
11
12 std::sort(pbegin, pend);
13 return pbegin[(pend - pbegin)/2];
14 }
From what I can understand, the method loops backwards through the blocks from the current block, populates the block time into an array, sort it (it’s already sorted), then picks the middle one (5) and returns that.
Is that correctly assumed?
Wouldn’t simply selecting index - 5 do the exact same thing? Of course one would need to calculate for genesis and the first 10 blocks, but that’s easy.
I was expecting this method to do something else, namely take the diff time (not the timestamp) between each block, then picking the middle one, which would give the average time between each block for the last 10 blocks. Another quick way to calculate, would be take GetBlockTime from the block 10 indexes back, diff with current block and divide by 10, should give one type of average.
The current code populates an array of 10 timestamps, but it only picks the one in the middle. There is no reason to populate it with 10 timestamps, as the 5 oldest are not used for anything. It also doesn’t use or calculate/care about any of the other blocks.
So if the last 5 blocks took:
1 hour 10 minutes 10 minutes 10 minutes 10 minutes 10 minutes 10 minutes 10 minutes 10 minutes 10 minutes
Then GetMedianTimePast will return a timestamp 1 hour and 40 minutes back in time from current block. I understand median is correct name for the method (it returns the middle of the sorted numbers), but is the numbers to be sorted suppose to be time between blocks (datediff) and not the actual timestamps?
The “medianTime” returned is also not the time between blocks, it is the time 5 blocks back. Which is why I’m wondering why not simply grab the datetime of the block 5 indexes back instead?
For for me to show the median time between blocks in the block explorer, I must take (BlockTime - MedianTime / 5). From what I know, I think the calculate is used for consensus/mining, and not suppose to be what I’m after (average block time), I can calculate that another way, but I stumbled upon this and initially thought it to be something else, and thought it could maybe be improved a bit?
Is that the way it is suppose to work, or am I not able to read the code properly? Thanks!