If your simulation indicates I’m correct, my reasoning is based on an excellent quote from Wikipedia on the Erlang distribution:
The Erlang and Poisson distributions are complementary, in that while the Poisson distribution counts the events that occur in a fixed amount of time, the Erlang distribution counts the amount of time until the occurrence of a fixed number of events.
Like the difficulty calculation, getnetworkhashrateps
has a fixed number of blocks from which it measures time. So time isn’t fixed as is required for Poisson to apply. Both difficulty and getnetworkhashrateps
are using a fixed amount of blocks which indicates Erlang is needed, and therefore the adjustment. To make Poisson apply (no adjustment), it seems we need to have a fixed amount of time from the current time to be looking into the past to count the blocks seen.
Another way to view it without needing to know the about Erlang distribution comes from the Poisson and another tweet you made, i.e. that if you randomly select a point in time, what’s the time to the previous block plus the time to the next block from that point? From the memorylessness property, it’s 1 blocktime before and 1 blocktime after, i.e. 2 block times. Let’s assume the most recent block timestamp is random and is OK to use. Poisson says we have to go a fixed amount of time in the past and count blocks in that timespan, so the initial time we choose for a fixed timespan should be as random as the most recent timestamp. We expect a random initial time point to have zero blocks for 1 blocktime before and 1 blocktime after it, but we’re selecting a timestamp for the time that is “on top” of a block. So that block from which we get our initial timestamp is exactly 1 block too many, so we need the adjustment (N-1)/N to subtract it out.