Make anti-leech choker really punish underreporters#8037
Make anti-leech choker really punish underreporters#8037Artoria2e5 wants to merge 1 commit intoarvidn:RC_2_0from
Conversation
We previously only prevented underreporting from working. But since we know they are underreporting, many by a factor of +Infinity, why not punish them?
|
arvidn
left a comment
There was a problem hiding this comment.
sorry for the delay. I finally put some thought into this. Any improvement is welcome, and maybe this is still an improvement, even if it's not perfect.
| // 2. The ramp-up for liars remains too slow. Hence we also calculate a | ||
| // "honesty" ratio as (sent_blks / (claimed_blks + 1)) to | ||
| // quickly increase the penalty for no-report and divide Chow's | ||
| // progress-score with it. |
There was a problem hiding this comment.
one important consideration with (2) is the inherent latency in receiving HAVE messages. The complete bandwidth-delay product will always be considered lied about, by this logic. The delay in this case is worse than just the network round-trip. The other end needs to:
- put it in the disk cache
- wait for the other blocks for the same piece to be downloaded
- hash the piece (and worst-case, have to read some blocks back from disk)
- queue a
HAVEmessage to be sent (which may end up behind otherPIECEmessages)
At high rates, this bandwidth delay product can easily be megabytes.
Another, perhaps less important, consideration is that this logic doesn't take into account which blocks were sent. A "cheater" that only downloads a single block per piece, but from 128 different peers, will be able to withhold 127/128 HAVE messages (99.2%) without triggering any suspicion (by this logic). This is assuming a piece size of 128 blocks, i.e. 2 MiB.
| float const dishonesty = std::min(1.f | ||
| , 1.f * float(given) / float(piece_length) / float(says_has + 1)); |
There was a problem hiding this comment.
I would prefer integer math here, only partly because of embedded systems but also to have deterministic results.
Since you divide by honesty below, couldn't you invert this, call it honesty and multiply it below? Then it might be reasonable to use an integer. e.g. std::int64 const honesty = std::max(1, piece_length * says_hash / (given + 1));
We previously only prevented underreporting from working. But since we can know some clients are underreporting, many by a factor of +Infinity, why not punish them?
The new change does just that. It divides the anti-leech score by the estimated under-reporting ratio. Of course we never estimate +Infinity because we do +1 on the divisor. Very light float32 math is used.
The comments are updated to explain the ways in which our solution differs from Chow et. al.