Pages:
Author

Topic: PPLNS - page 2. (Read 63139 times)

newbie
Activity: 19
Merit: 0
June 24, 2013, 12:23:10 PM
#31
Thanks for that explanation.

Regarding the small correction you made, I don't quite understand what's happening.
Are we talking about the "oldest" share, the one that may get a partial reward (in order to get the total score to exactly X)?
If so, I don't see how "t" is relevant to the calculation, if "t" is the score of the "winning share" (i.e. the share that we didn't even take into consideration to begin with).

My final question: Is X=2 an acceptable setting for real-world usage?
donator
Activity: 2058
Merit: 1054
June 22, 2013, 03:10:50 PM
#30
I am currently implementing the "correct method" PPLNS and I have one question.

When a block is found, is the "winning share" counted in the window? (the original post suggests that it isn't)
If it isn't counted, what is the reasoning behind this?
Correct, it isn't.

If you included it, the expected payout for a share would depend on future difficulty changes. For example let X=1 and take an extreme case where after I submit a share, the difficulty changes to 1. Then the next share found will be a block and it will take the entire reward, and I will get nothing.

The same happens if instead of the global difficulty changing, a different share difficulty is submitted.

In practice the differences will be minor because shares are small. Where the difference between the naive method and the unit-based method is measured in percentage, the difference in how you count the edges is measured in ppm.

Actually, the question prompted me to revisit the model (it's been a while), and I noticed there was a small correction which I included in AoBPMRS but didn't fix in this post; for the last share, instead of a payout of (srB)/(tX), it should be (sB)/(tX) * min (r,t). I fixed it now.

PS. You should consider shift-PPLNS, I've specified the exact way to do it in this comment.
newbie
Activity: 19
Merit: 0
June 22, 2013, 03:12:59 AM
#29
I am currently implementing the "correct method" PPLNS and I have one question.

When a block is found, is the "winning share" counted in the window? (the original post suggests that it isn't)
If it isn't counted, what is the reasoning behind this?
donator
Activity: 2058
Merit: 1054
April 25, 2013, 11:52:31 AM
#28
PPLNS is "supposed to be" a method where there is no operator risk, he just pays out the rewards for each block in some way. However, for the method (or any other method) to be hopping-proof even when the block reward changes, this is no longer the case.

Shares are still paid (Bd / DX) duntil the total of d/D reaches X. If, when a block is found, the reward is low in comparison to the reward at the time recent shares were submitted, the amount he has to pay according to the method is higher than the block reward, and he must pay the difference from his own pocket. And conversely, if the actual block reward is higher he keeps the difference.


If B is highly variable it can cause quite a lot of risk to the operator. It could be mitigated by basing the credit per share not only on the expected contribution but also the variance created.


In pay-once PPLNS you know the maximum amount you can be paid for a share, but you don't know whether you'll be paid it at all or not. It's not just that you don't know when you'll get it. Future B has no effect on whether you get paid and when.
sr. member
Activity: 434
Merit: 250
April 24, 2013, 06:34:57 PM
#27
I added in a later comment that to be protected from hopping based on block reward (which will be critical when the reward is based on tx fees), B for each share needs to be chosen when the share is submitted, not when the block is found.

When a reward drop is coming up, like when Bitcoin went from 50 to 25, the shares submitted before the drop would be earning twice the reward as the shares after the drop if you store credit by current potential reward at the time of submission instead of the actual reward at the time a block is found. Is that that intentional? In a pure PPS model, that's how it'd have worked of course. But in a pay-once PPNLS model you can only pay back as many shares as you actually received from the found block. So if the D shares up to the reward drop didn't find a block, then D+1 finds a block with half the reward, you're only going to be able to pay the most recent D/2 shares. It seems a bit counter intuitive to me, I'd think the last D shares would all get paid on the actual block (half reward than if we found the block sooner, but it is what it is, you can only pay out what the pool receives).

I guess the same applies long-term with transaction fee based blocks, although then the reward would be going up and down from block to block.

For pay-once, does it just boil down to this then:

1- Knowing exactly what you are earning (share of potential reward+fees for current block, the reward you earned never changes between now and when you get paid) but not knowing how long until you get paid (if reward drops, your time until getting paid increases if your shares weren't recent enough)

OR

2- Knowing a better idea when you get paid (based on average time to solve blocks regardless of varying reward) but not knowing how much you'll earn (reward+transaction fees of the block actually found in the future).

As far as I understand things currently, most PPS models (should, if coded to use reward at time of share) fall under #1. Pay-Once-PPLNS using block rewards at time shares are submitted would also fall under #1. Proportional would fall under #2.
sr. member
Activity: 434
Merit: 250
April 24, 2013, 08:55:50 AM
#26
Ah okay, excellent. The initial pool I'm setting up is for TRC where the difficulty changes with each block. I store in my shares database d (user selected difficulty) and D (difficulty of the block you just submitted a share for) but do all of the payment logic based on sum(d/D for each share submitted individually, ie: D will vary over time) in LIFO (most recent) order. I mark shares if paid and then ignore them moving forward (stored for graphing and historical record).

The only thing I'm not doing is storing the reward based on B at the time you submit a share. I was only storing "You have earned sum(d/D) blocks" and then pay it out when a block is found based on the reward of the block found, not the reward at the time of submission. Which is exactly what you said not to do. I'll need to look at that.
donator
Activity: 2058
Merit: 1054
April 24, 2013, 04:23:32 AM
#25
If you want a simple hopping-proof method, PPLNS is it (not the pay-once variant), assuming it's implemented correctly.
Is there a hopping proof way to implement the pay-once variant? Assuming you store d/D as your score for shares submitted as you outline in original post (this is the way I store share data already).
To be clear, when I said pay-once isn't it, I meant it's not simple, not that it's not hopping-proof.

I think if you follow the original method, and just cap the payment for each share to (sB/X), skipping already paid shares, it will work fine and be protected from hopping based on both pool past and future difficulty changes. You'll need to keep for each share not only whether it was paid, but how much, so if it was partially paid, it can be paid more in future blocks.

I added in a later comment that to be protected from hopping based on block reward (which will be critical when the reward is based on tx fees), B for each share needs to be chosen when the share is submitted, not when the block is found.
sr. member
Activity: 434
Merit: 250
April 23, 2013, 06:26:56 PM
#24
If you want a simple hopping-proof method, PPLNS is it (not the pay-once variant), assuming it's implemented correctly.

Is there a hopping proof way to implement the pay-once variant? Assuming you store d/D as your score for shares submitted as you outline in original post (this is the way I store share data already).
donator
Activity: 2058
Merit: 1054
April 23, 2013, 04:42:26 PM
#23
I should probably force myself to go with DGM and be done with it. I just like the simplicity of CPPSRB.
If you want a simple hopping-proof method, PPLNS is it (not the pay-once variant), assuming it's implemented correctly. Or shift-PPLNS which is more scaleable.

Thank you for your time and for writing the Analysis paper.
You're welcome.
sr. member
Activity: 434
Merit: 250
April 23, 2013, 01:28:03 PM
#22
To be really wacky one could do pay-twice-PPLNS with X=2.

I should probably force myself to go with DGM and be done with it. I just like the simplicity of CPPSRB.

Thank you for your time and for writing the Analysis paper.
donator
Activity: 2058
Merit: 1054
April 23, 2013, 11:54:43 AM
#21
Not really. If for example X=0.5 then still normally a block will be paid out 100% to recent miners - each share will be paid twice the PPS rate. But in lucky times when there aren't enough unpaid shares, past miners can be paid.

An X < 1 will further increase the time to maturity on old shares, won't it? Is there a way in a pay-once-PPLNS model to avoid an unbounded time to maturity?
It's variance, not maturity time. A miner submitting a share has a chance to get more than the PPS amount, but also a chance to get nothing at all, ever. If he does get paid, it will be with high probability in a short time.
sr. member
Activity: 434
Merit: 250
April 23, 2013, 11:26:17 AM
#20
Not really. If for example X=0.5 then still normally a block will be paid out 100% to recent miners - each share will be paid twice the PPS rate. But in lucky times when there aren't enough unpaid shares, past miners can be paid.

An X < 1 will further increase the time to maturity on old shares, won't it? Is there a way in a pay-once-PPLNS model to avoid an unbounded time to maturity?
donator
Activity: 2058
Merit: 1054
April 23, 2013, 06:16:21 AM
#19
A substantially different variant is to pay for every share at most once. If, when going backwards in the list of shares, we encounter some that were already paid, we skip them and move on to older shares. X needs to be less than 1 to make sure that eventually we will have enough unpaid shares to draw on. I'm not sure what's the correct way to handle difficulty changes with this variant.
In effect, like a pool charging a 1% fee but paying that fee to past-due shares instead of it going to the operator?
Not really. If for example X=0.5 then still normally a block will be paid out 100% to recent miners - each share will be paid twice the PPS rate. But in lucky times when there aren't enough unpaid shares, past miners can be paid.

Payment always starts at the last share and continuously moves backward as much as possible, skipping any already paid shares.
legendary
Activity: 2576
Merit: 1186
April 22, 2013, 04:33:46 PM
#18
A substantially different variant is to pay for every share at most once. If, when going backwards in the list of shares, we encounter some that were already paid, we skip them and move on to older shares. X needs to be less than 1 to make sure that eventually we will have enough unpaid shares to draw on. I'm not sure what's the correct way to handle difficulty changes with this variant.

Is this in effect what CPPSRB does? It pays all shares only once, starting with the most recent and going back as far as needed to pay out the full block (or until every share is paid). Your % of the block reward is the sum of all of your d/D since last block, where the total shares we're paying is = block difficulty of the block we just found.
The difference I see, is that if CPPSRB pays off all shares, it saves the excess for the next block.
sr. member
Activity: 434
Merit: 250
April 22, 2013, 04:28:43 PM
#17
A substantially different variant is to pay for every share at most once. If, when going backwards in the list of shares, we encounter some that were already paid, we skip them and move on to older shares. X needs to be less than 1 to make sure that eventually we will have enough unpaid shares to draw on. I'm not sure what's the correct way to handle difficulty changes with this variant.

Is this in effect what CPPSRB does? It pays all shares only once, starting with the most recent and going back as far as needed to pay out the full block (or until every share is paid). Your % of the block reward is the sum of all of your d/D since last block, where the total shares we're paying is = block difficulty of the block we just found.

Your comment on X being less than 1 to avoid an endless backlog is what caught my attention. Is the way I should think of that, if X is .99 then miners are making 99% of the reward and 1% is being kept back to pay shares older than the miners normally being paid. In effect, like a pool charging a 1% fee but paying that fee to past-due shares instead of it going to the operator?
donator
Activity: 2058
Merit: 1054
February 25, 2012, 05:35:16 PM
#16
You need to distinguish score (which in some other places I call "units") from reward. Score is s=1/D and is the thing that should total X. (from the OP, "a score of 1/D... until you reach a share which brings the total score of the shares counted above X".) Reward is what you pay for each included share, and is s*B/X.

I hope there are some pieces to the computation you're not showing here, because some things are missing with respect to the accurate variant. In particular, you need D and B to be the values at the time the share was submitted rather than at the time payments are handed out (the OP clarifies this for D, but was written before I realized this is also true for B), and for absolute accuracy you need to proportionally discount the reward for the earliest share (the one that brings the total score to X).
sr. member
Activity: 403
Merit: 250
February 25, 2012, 05:18:15 PM
#15
Doing a bit of bumping right now, but i think it's appropriate.
We at Bitlc.net is changing from Propotional to PPLNS as soon as possible, but first I want to clarify something.

I'm struggling to understand your algorithm in the first post, i don't really get how X=2 results in payments for difficulty*2 (?)

This is my algorithm (in PHP), more or less:

Quote
$total = 0;
$N = 0;

$X = 2; // Magic number
$D = 1376302.267886; // Curr difficulty
$s = 1/$D; // Share score
$B = 50; // Block reward

$reward = ($s * $B) / $X; // per share

while($X > $total) {
        $N++; // Increment the share count, just to check how many shares that actually would be paid.
        $total = $total + $reward; // Total score
}

Results in:
$total = 2.0000148689956; // Total score
$N = 110105; // So 110105 shares was paid(?)

I've seen that people are using diff/2 (N = 688151 shares) and diff*2 (N = 2752604 shares)
What is it that i don't understand? Why does my code above results in N = 110105? :/

Thanks for any help that i can get.

--
Regards, Jim


EDIT: Oh crap, while writing this i just realized that i might have read wrong in the original post.
Each share is worth $s - NOT $reward ?

Please confirm if this is the case Smiley
donator
Activity: 2058
Merit: 1054
September 03, 2011, 02:07:24 PM
#14
I am currently considering this variation for my pool: PPLNS=Pay Per Last N Shifts
This is less resource-intensive than shiftless 0-1 PPLNS, but I don't find it simpler. I think exponential PPLNS is simplest in both presentation and resources (since you only need to keep track of one number per worker). For a full description of this, take the double geometric method with o=1. Note that for display purposes the relevant quantity is S/s.

I'd base shifts on a specified quantity of score. Suppose X=0.1, if a shift starts at D=1M, 50K shares are submitted, then D increases to 2M and 100K more shares are submitted, this completes a shift (50K/1M + 100K/2M = 0.1).

It's ok to change X between shifts and to base shifts on units of time, as long as you don't end shifts based on number of blocks found. Any block found in a shift of size X, gives a reward of (B*S)/(N*X) to any worker whose total score in the previous N shifts is S.

The idea is: If I submit a share, I get score p which qualifies me to an expected reward of pB. For each of the next N shifts, the expected number of blocks found is X (where X is specific to that shift), so if I'm rewarded (B*p)/(N*X) per block that's on average pB/N for any future shift, and since there are N the average reward is pB.
legendary
Activity: 2730
Merit: 1034
Needs more jiggawatts
September 02, 2011, 11:34:15 AM
#13
I am currently considering this variation for my pool: PPLNS=Pay Per Last N Shifts

D = difficulty
N = number of shifts eligible for payment
D2S = difficulty to shift ratio

Number of shares that go in a shift = D/D2S

Stored for each shift:
Number of shares for each user

When receiving any proof of work:
Increment the user's number of shares in the current shift
Unless the total number of shares in the shift exceeds D/D2S, in that case start a new shift and mark the old as completed

When receiving a generating proof of work:
For the last N completed shifts, weight=total_shares_in_shift
Distribute income proportionally among shifts according to their weight, and proportionally within shifts according to how many shares each user has.

As long as shifts are weighted, it might work out ok to pay for last N hours as well. Just start new shifts every hour instead of when the current shift reaches a certain size.

Benefits:
  • Fairly simple; easier to understand and to audit.
  • More transparent; easier to display all the data from which a user's payment was calculated.
  • Much lower storage and processing costs for server. Side-effect: easier to show live statistics and future payment estimates.

To avoid the time around difficulty changes from being hoppable it may be necessary to weight shifts also by their difficulty.

Any thoughts?
sr. member
Activity: 404
Merit: 250
September 01, 2011, 12:12:50 PM
#12
If there are 10 pools like this, can't I set them all up to be .1N a day in advance or whatever, mine for a bit at one, and then bump up the N and jump to the next .1N pool? Especially if you allow people to change their N at will, they can just make it float along so that their last batch of mined blocks is always in focus, until they drop it back to the minimum and begin mining again.
I'm not sure I understand what you mean, but I think you missed the point that you can configure what X will be for the future shares you submit to the pool, not for past shares. Although there's no problem with changing X for past shares, as long as they're rescaled to maintain the same expected payout.

You are right, I misunderstood. Thanks!
Pages:
Jump to: