Now consider the rule defined by those 3 lines I was talking about. It states "If a share (S) is based on stale block, mine on its parent (P)." (That's what "Punishing for block-stale / Jumping to ..." log message is about.) If a miner (either intentionally or because of slow bitcoind) disrespects this rule, not only he loses nothing, but may also eventually profit from it! Really, his share A (a child of block-stale share S, which is punished by the rest of the network) is 1 share ahead of "proper" miner's share B, which is P's child. As a result, A will have priority over B even if B is found earlier!
Should I report a bug on GitHub?
You should. But read below why I think it's not high priority.
2 cases in your example:
- local bitcoind lagging: miner is punished most of the time so it is prevented to benefit from worthless work as intended and is motivated to upgrade his/her configuration
- node trying to make his share more resilient by avoiding to build on the parent share
In the "more resilient attack" the node can only attack after one out of 20 shares (30s share interval with 10mn block interval) if and only if it is from a slow node producing a stale share
A node does not have to be slow to produce a block-stale share. Any non-block-stale share will become block-stale after a new block.
(assuming we don't have nodes more than 30-60s behind the Bitcoin network able to make 2 successive stale shares).
With high-hashrate nodes it gets even worse because any
node doesn't punish own block-stales:
if (self.header['previous_block'], self.header['bits']) != (previous_block, bits) and self.header_hash != previous_block and self.peer_addr is not None:
return True, 'Block-stale detected! %x < %x' % (self.header['previous_block'], previous_block)
So a massive node doesn't even have to be slow to orphan other's shares.
- if another node finds a share before him he will automatically switch to it as building on either fork doesn't give him any benefit anymore
With 10% global stales, which corresponds to about 3s effective latency on average, he has those 3s or even more to send his share to other peers before he receives and processes that other's share. Once sent to any, even just 1 peer, his share will definitely orphan the "proper" one.
- if he finds a share before the rest of the network, he won't have gained anything (he has as much chances of that happening when mining on the parent share)
- the only gain is when he finds a share that collides with another : there he will be sure to win instead of having ~50% chances
So someone trying this attack will get benefit for less than 5% (1 in 20 at most, probably far less) of his expected DOA+Orphan rate (which seems to be ~10% since we switched to a 30s share interval) and this benefit will be ~50%.
If he has high latency, both your estimates are wrong. Someone may have even 20% stales and sure to win instead of having ~10% chances. In this case, his expected benefit is...
So in the most pathological case where 100% of the network produces stale shares (built with the previous block), the expected benefit is only 50% of 10% of 5% : 0.25%.
90% of 20% of 5% = 0.9%
Most nodes probably don't produce stale shares, so this is more likely a ~0.1% advantage.
As I stated before, every node produces block-stale shares, because a good share becomes a block-stale after block switch.
Now what is the attacker losing? If you don't punish slow nodes you are hurting yourself as much as the rest of the network by validating wasted work. The exception is the slow node which is grateful to be paid for worthless work.
For every gained share you are validating one worthless share. If everyone did this, everyone would lose money to worthless shares producers instead of gaining 0.1%. Now it's too late for me to try to estimate how much is lost but disabling the protection might not be a good idea, especially if many are doing it. It probably would end in a "tragedy of the commons": you can gain a bit by doing it, but when everyone does it, everyone loses.
Again, most punished shares are good shares turned block-stale by a new block. That means with hash < block target, they would have been a valid block at the time they were found.
Allowing worthless work allows it to rise without limits: if there are very slow bitcoinds with very high hashrate they could make 2 or more consecutive stale shares a frequent occasion and rise the worthless hashrate to 10 or more percent of the whole pool.
One solution might be to ignore stale shares when comparing the different sharechain forks. People disabling the protection would get no benefit at all.
Exactly! Jumping to a fork with same height but less block-stales is right. Jumping to the parent is nonsense.
Disabling this jumping is essential not only for slow nodes. Look, while a new bitcoin block is propagated by the network, some p2pool nodes receive it earlier, some later. At this time, it's better for anyone to be safe and work on the last share instead of its parent.
In the meanwhile, advocating to remove the protection is an attack on P2Pool, please stop doing it unless you want to participate in your own reduced income.
I haven't removed the punishing itself but only disabled jumping to parent share. When comparing two forks, it's still active.
And people here complain that they have their good shares orphaned all the time by this mechanism. Why should they have reduced income because someone else (with much higher hashrate) doesn't care about tuning his node?