Partial Slashing
djrtwo opened this issue · 3 comments
Issue
Need to implement partial slashing to reduce the discouragement of validating for the occasional not-so-malicious incorrectly signed messages.
Proposed Implementation
The following is a rough outline and needs to be cleaned up
- maintain a mapping epoch => total_slashed, keeping track of the total amount of validator deposits removed through slashing up until that point. When you initialize a new epoch, set total_slashed[now] = total_slashed[now - 1], so the total carries over.
- let recently_slashed = total_slashed[now] - total_slashed[now - withdrawal_delay]
- When a validator is slashed, add their entire deposit size to total_slashed[now]
- When a validator gets slashed, forcibly log them out for dynasty
n+1
. Set a flag forcing them to be slashed when they withdraw. When they initiate the withdrawal, the following fraction of their deposit is slashed
fraction_to_slash = (total_slashed[withdraw_time] - total_slashed[withdraw_time - 2 * withdrawal_delay]) * 6 / total_deposits_at_logout
Additionally their deposit is calculated based on the deposit_scale_factor at time of withdrawal, so they have to suffer all inactivity penalties up until the block during which they withdraw
This slashing occurring at withdrawal ensures that if a coordinated attack occurs and a significant amount of validators are slashed, then the attackers all suffer equal magnitude slashing.
I have a few questions.
- What is
recently_slashed
for? - How the numbers(2 and 6) are decided in
(total_slashed[withdraw_time] - total_slashed[withdraw_time - 2 * withdrawal_delay]) * 6
?
I think I need to read articles(if exist) about the reasoning behind slashing conditions and parameters including this, like sharding spec. Where can I find it?
What is recently_slashed for?
The intention is to slash validators by an amount proportional to the percentage of other validators that were slashed around the same time. recently_slashed
is the numerator.
Aah, sorry, I think it's meant to be equal to total_slashed[withdraw_time] - total_slashed[withdraw_time - 2 * withdrawal_delay]
How the numbers(2 and 6) are decided in (total_slashed[withdraw_time] - total_slashed[withdraw_time - 2 * withdrawal_delay]) * 6?
The 2 basically means that if you commit a violation at time T, you're slashed based on the portion of validators that misbehaved between time [T - withdrawal_delay, T + withdrawal_delay]
The 6 makes the slashing 100% if 16.667% of validators are slashed. Originally the interval was [T - withdrawal_delay, T]
which meant that if 1/3 were slashed due to the attack, the validators that are slashed first would lose less, making the attack 25% less costly; if the denominator was more forgiving (eg. 3) then the attackers would lose far less. Now that the interval wraps around in both directions, I actually would favor decreasing the 6 to a 3.