-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6933b0d
commit a0d236d
Showing
5 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package transition | ||
|
||
import "github.com/ledgerwatch/erigon/cl/clparams" | ||
|
||
func (s *StateTransistor) processSlashings(slashingMultiplier uint64) error { | ||
// Get the current epoch | ||
epoch := s.state.Epoch() | ||
// Get the total active balance | ||
totalBalance, err := s.state.GetTotalActiveBalance() | ||
if err != nil { | ||
return err | ||
} | ||
// Calculate the total slashing amount | ||
// by summing all slashings and multiplying by the provided multiplier | ||
slashing := s.state.GetTotalSlashingAmount() * slashingMultiplier | ||
// Adjust the total slashing amount to be no greater than the total active balance | ||
if totalBalance < slashing { | ||
slashing = totalBalance | ||
} | ||
// Apply penalties to validators who have been slashed and reached the withdrawable epoch | ||
for i, validator := range s.state.Validators() { | ||
if !validator.Slashed || epoch+s.beaconConfig.EpochsPerSlashingsVector/2 != validator.WithdrawableEpoch { | ||
continue | ||
} | ||
// Get the effective balance increment | ||
increment := s.beaconConfig.EffectiveBalanceIncrement | ||
// Calculate the penalty numerator by multiplying the validator's effective balance by the total slashing amount | ||
penaltyNumerator := validator.EffectiveBalance / increment * slashing | ||
// Calculate the penalty by dividing the penalty numerator by the total balance and multiplying by the increment | ||
penalty := penaltyNumerator / totalBalance * increment | ||
// Decrease the validator's balance by the calculated penalty | ||
s.state.DecreaseBalance(uint64(i), penalty) | ||
} | ||
return nil | ||
} | ||
|
||
func (s *StateTransistor) ProcessSlashings() error { | ||
// Depending on the version of the state, use different multipliers | ||
switch s.state.Version() { | ||
case clparams.Phase0Version: | ||
return s.processSlashings(s.beaconConfig.ProportionalSlashingMultiplier) | ||
case clparams.AltairVersion: | ||
return s.processSlashings(s.beaconConfig.ProportionalSlashingMultiplierAltair) | ||
default: | ||
return s.processSlashings(s.beaconConfig.ProportionalSlashingMultiplierBellatrix) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package transition_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/ledgerwatch/erigon/cl/clparams" | ||
"github.com/ledgerwatch/erigon/cl/cltypes" | ||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state" | ||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/transition" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestProcessSlashingsNoSlash(t *testing.T) { | ||
base := state.GetEmptyBeaconStateWithVersion(clparams.AltairVersion) | ||
base.AddValidator(&cltypes.Validator{ | ||
Slashed: true, | ||
}) | ||
base.AddBalance(clparams.MainnetBeaconConfig.MaxEffectiveBalance) | ||
base.SetSlashingSegmentAt(0, 0) | ||
base.SetSlashingSegmentAt(1, 1e9) | ||
s := transition.New(base, &clparams.MainnetBeaconConfig, nil) | ||
require.NoError(t, s.ProcessSlashings()) | ||
wanted := clparams.MainnetBeaconConfig.MaxEffectiveBalance | ||
require.Equal(t, wanted, base.Balances()[0], "Unexpected slashed balance") | ||
} | ||
|
||
func getTestStateSlashings1() *state.BeaconState { | ||
state := state.GetEmptyBeaconStateWithVersion(clparams.AltairVersion) | ||
state.AddValidator(&cltypes.Validator{Slashed: true, | ||
WithdrawableEpoch: clparams.MainnetBeaconConfig.EpochsPerSlashingsVector / 2, | ||
EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance}) | ||
state.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance}) | ||
state.SetBalances([]uint64{clparams.MainnetBeaconConfig.MaxEffectiveBalance, clparams.MainnetBeaconConfig.MaxEffectiveBalance}) | ||
state.SetSlashingSegmentAt(0, 0) | ||
state.SetSlashingSegmentAt(1, 1e9) | ||
return state | ||
} | ||
|
||
func getTestStateSlashings2() *state.BeaconState { | ||
state := getTestStateSlashings1() | ||
state.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance}) | ||
return state | ||
} | ||
|
||
func getTestStateSlashings3() *state.BeaconState { | ||
state := getTestStateSlashings2() | ||
state.SetSlashingSegmentAt(1, 2*1e9) | ||
return state | ||
} | ||
|
||
func getTestStateSlashings4() *state.BeaconState { | ||
state := getTestStateSlashings1() | ||
state.SetValidatorAt(1, &cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance - clparams.MainnetBeaconConfig.EffectiveBalanceIncrement}) | ||
state.SetBalances([]uint64{clparams.MainnetBeaconConfig.MaxEffectiveBalance - clparams.MainnetBeaconConfig.EffectiveBalanceIncrement, clparams.MainnetBeaconConfig.MaxEffectiveBalance - clparams.MainnetBeaconConfig.EffectiveBalanceIncrement}) | ||
return state | ||
} | ||
|
||
func TestProcessSlashingsSlash(t *testing.T) { | ||
tests := []struct { | ||
state *state.BeaconState | ||
want uint64 | ||
}{ | ||
{ | ||
state: getTestStateSlashings1(), | ||
want: uint64(30000000000), | ||
}, | ||
{ | ||
state: getTestStateSlashings2(), | ||
want: uint64(31000000000), | ||
}, | ||
{ | ||
state: getTestStateSlashings3(), | ||
want: uint64(30000000000), | ||
}, | ||
{ | ||
state: getTestStateSlashings4(), | ||
want: uint64(29000000000), | ||
}, | ||
} | ||
|
||
for i, tt := range tests { | ||
t.Run(fmt.Sprint(i), func(t *testing.T) { | ||
transitistor := transition.New(tt.state, &clparams.MainnetBeaconConfig, nil) | ||
require.NoError(t, transitistor.ProcessSlashings()) | ||
assert.Equal(t, tt.want, tt.state.Balances()[0]) | ||
}) | ||
} | ||
} | ||
|
||
/* | ||
func TestProcessSlashings_SlashedLess(t *testing.T) { | ||
} | ||
*/ |