PPLNS implementation Quote from Meni Rosenfeld's post explaining PPLNS:


  
  Choose a parameter X, which represents multiples of D to include in the window when difficulty is static. X=2 is a good choice. When a
  share is submitted, assign to it a score of 1/D, where D is the
  difficulty at the time the share is submitted.
  When a block is found, pay (sB)/X for the last share (the one before the winning share), where s is the share's score and B is the
  block reward. Continue backwards, paying each share based on its
  score, until you reach a share which brings the total score of the
  shares counted above X. Pay that share the amount (sB)/(tX) * min
  (r,t), where r is the score required to bring the total to exactly X
  and t is the score of the winning share. Don't pay any older shares.
  If the pool has just started, and a block is found before there are shares totaling a score of X, there will be leftover rewards and
  it should be decided what to do with them. It doesn't matter much, but
  I recommend that the operator keeps them (in a macroscopic view, if
  the pool ever changes, this is compensation for the funds needed to
  cash participants out). Other options include donating to charity, or
  distributing among the miners.
  


So far so good. One thing I'm struggling to understand is where the difficulty of a share itself fits into the picture. How do I scale the reward by share difficulty without screwing up the algorithm?

Update:

What I also would like to know is how to handle cases where the network difficulty recorded with a share is different from the current network difficulty.
Well, that post is quite old. Variable-difficulty shares weren't a thing then.

That said, I'm pretty sure the fix is as follows: When a share is submitted, the post says you should assign to it a score of 1/D. Instead, assign to it a score of d/D, where d is the share's difficulty. That's it.

Also, you should have a look at https://bitcoil.co.il/pool_analysis.pdf, specifically the "unit-PPLNS" part of section 3.3. It's slightly more complicated, but IIRC it has the advantage that it is still hopping-proof when the block reward can change (which is much more relevant now than it was back then).

As for changes in the network difficulty - the score is based on the historical difficulty, and the current difficulty is not used at all in the calculation.

If this seems odd, consider that if the current network difficulty is higher, than each new share has less chance to become a block and reward historical shares, but on the other hand, have a lower score and thus more shares are needed until the historical share is out of the window. So it evens out.